35#include "./base/base_uses.f90"
42 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'gw_ri_rs_grid_optimization'
44 TYPE,
PRIVATE :: local_cluster_3c_integrals_type
45 INTEGER,
ALLOCATABLE :: atom_indices(:)
46 REAL(KIND=
dp),
ALLOCATABLE :: int_3c(:, :, :)
47 END TYPE local_cluster_3c_integrals_type
58 CHARACTER(len=*),
PARAMETER :: routinen =
'optimize_ri_rs_grid'
61 TYPE(local_cluster_3c_integrals_type),
ALLOCATABLE :: cluster_3c_int(:)
63 CALL timeset(routinen, handle)
66 CALL validate_ri_rs_grid_optimization_input(bs_env)
72 CALL prepare_ri_rs_grid_optimization(bs_env)
75 CALL build_cluster_3c_int(bs_env, cluster_3c_int)
79 CALL optimize_grid_coordinates(bs_env, cluster_3c_int)
89 SUBROUTINE validate_ri_rs_grid_optimization_input(bs_env)
92 INTEGER :: iatom, ikind
94 cpassert(
ASSOCIATED(bs_env%ri_rs%cell))
95 cpassert(
ASSOCIATED(bs_env%ri_rs%particle_set))
96 cpassert(
ASSOCIATED(bs_env%para_env))
97 cpassert(
ALLOCATED(bs_env%basis_set_AO))
98 cpassert(
ALLOCATED(bs_env%basis_set_RI))
99 cpassert(
ALLOCATED(bs_env%sizes_AO))
100 cpassert(
SIZE(bs_env%ri_rs%particle_set) == bs_env%n_atom)
101 cpassert(
SIZE(bs_env%sizes_AO) == bs_env%n_atom)
102 cpassert(
SIZE(bs_env%basis_set_AO) ==
SIZE(bs_env%basis_set_RI))
104 IF (bs_env%ri_rs%grid_opt%rs_ao_ratio <= 0.0_dp)
THEN
105 cpabort(
"GRID_OPTIMIZATION%RS_AO_RATIO must be positive")
107 IF (bs_env%ri_rs%grid_opt%cutoff_atomic_cluster <= 0.0_dp)
THEN
108 cpabort(
"GRID_OPTIMIZATION%CUTOFF_ATOMIC_CLUSTER must be positive")
110 IF (bs_env%ri_rs%grid_opt%max_iter < 1)
THEN
111 cpabort(
"GRID_OPTIMIZATION%MAX_ITER must be positive")
113 IF (bs_env%ri_rs%tikhonov < 0.0_dp)
THEN
114 cpabort(
"RI_RS%TIKHONOV must not be negative")
117 DO iatom = 1, bs_env%n_atom
118 ikind = bs_env%ri_rs%particle_set(iatom)%atomic_kind%kind_number
119 cpassert(ikind >= 1 .AND. ikind <=
SIZE(bs_env%basis_set_AO))
120 cpassert(
ASSOCIATED(bs_env%basis_set_AO(ikind)%gto_basis_set))
121 cpassert(
ASSOCIATED(bs_env%basis_set_RI(ikind)%gto_basis_set))
122 IF (bs_env%sizes_AO(iatom) < 1 .OR. &
123 bs_env%basis_set_RI(ikind)%gto_basis_set%nsgf < 1)
THEN
124 cpabort(
"Every atom in GRID_OPTIMIZATION needs ORB and RI_AUX functions")
127 END SUBROUTINE validate_ri_rs_grid_optimization_input
133 SUBROUTINE prepare_ri_rs_grid_optimization(bs_env)
136 INTEGER :: iatom, unit_nr
138 cpassert(
ALLOCATED(bs_env%ri_rs%atomic_grids))
139 cpassert(
SIZE(bs_env%ri_rs%atomic_grids) == bs_env%n_atom)
141 DO iatom = 1, bs_env%n_atom
142 cpassert(
ALLOCATED(bs_env%ri_rs%atomic_grids(iatom)%raw_points))
143 cpassert(
SIZE(bs_env%ri_rs%atomic_grids(iatom)%raw_points, 1) == 3)
144 cpassert(
SIZE(bs_env%ri_rs%atomic_grids(iatom)%raw_points, 2) > 0)
147 unit_nr = bs_env%unit_nr
148 IF (unit_nr > 0)
THEN
149 WRITE (unit_nr,
'(T2,A)')
'Started RI-RS grid optimization'
152 END SUBROUTINE prepare_ri_rs_grid_optimization
165 SUBROUTINE grid_objective(grid_coordinates, atom_coordinate_offsets, bs_env, cluster_3c_int, &
166 normalized_error, coordinate_gradient, &
167 max_abs_error, fit_successful)
168 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: grid_coordinates
169 INTEGER,
DIMENSION(:),
INTENT(IN) :: atom_coordinate_offsets
171 TYPE(local_cluster_3c_integrals_type), &
172 DIMENSION(:),
INTENT(IN) :: cluster_3c_int
173 REAL(kind=
dp),
INTENT(OUT) :: normalized_error
174 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: coordinate_gradient
175 REAL(kind=
dp),
INTENT(OUT) :: max_abs_error
176 LOGICAL,
INTENT(OUT) :: fit_successful
178 INTEGER :: evaluated_cluster_count, icluster, &
180 LOGICAL :: cluster_fit_successful
181 REAL(kind=
dp) :: cluster_max_abs_error, &
182 cluster_normalized_error
183 REAL(kind=
dp),
ALLOCATABLE :: cluster_coordinate_gradient(:, :)
186 para_env => bs_env%para_env
187 cpassert(
SIZE(coordinate_gradient) ==
SIZE(grid_coordinates))
188 CALL unpack_lbfgs_grid_coordinates(grid_coordinates, atom_coordinate_offsets, &
189 bs_env%ri_rs%atomic_grids)
190 normalized_error = 0.0_dp
191 coordinate_gradient = 0.0_dp
192 evaluated_cluster_count = 0
193 max_abs_error = 0.0_dp
194 fit_successful = .true.
195 DO icluster = 1,
SIZE(cluster_3c_int)
196 CALL evaluate_local_cluster(cluster_3c_int(icluster), bs_env, &
197 cluster_normalized_error, cluster_coordinate_gradient, &
198 cluster_max_abs_error, cluster_fit_successful)
199 IF (.NOT. cluster_fit_successful)
THEN
200 fit_successful = .false.
201 IF (
ALLOCATED(cluster_coordinate_gradient))
DEALLOCATE (cluster_coordinate_gradient)
204 normalized_error = normalized_error + cluster_normalized_error
205 CALL accumulate_atom_gradient(cluster_3c_int(icluster)%atom_indices, &
206 bs_env%ri_rs%atomic_grids, &
207 atom_coordinate_offsets, cluster_coordinate_gradient, &
209 evaluated_cluster_count = evaluated_cluster_count + 1
211 max(max_abs_error, cluster_max_abs_error)
212 DEALLOCATE (cluster_coordinate_gradient)
214 successful_ranks = merge(1, 0, fit_successful)
215 CALL para_env%sum(normalized_error)
216 CALL para_env%sum(coordinate_gradient)
217 CALL para_env%sum(evaluated_cluster_count)
218 CALL para_env%sum(successful_ranks)
219 CALL para_env%max(max_abs_error)
220 fit_successful = evaluated_cluster_count == bs_env%n_atom .AND. &
221 successful_ranks == para_env%num_pe
222 IF (.NOT. fit_successful)
THEN
223 normalized_error = huge(normalized_error)
224 coordinate_gradient = 0.0_dp
228 normalized_error = normalized_error/real(bs_env%n_atom,
dp)
229 coordinate_gradient = coordinate_gradient/real(bs_env%n_atom,
dp)
230 END SUBROUTINE grid_objective
237 SUBROUTINE optimize_grid_coordinates(bs_env, cluster_3c_int)
239 TYPE(local_cluster_3c_integrals_type), &
240 DIMENSION(:),
INTENT(IN) :: cluster_3c_int
242 INTEGER,
PARAMETER :: lbfgs_history = 7
243 REAL(kind=
dp),
PARAMETER :: lbfgs_factr = 0.0_dp, &
244 lbfgs_pgtol = 1.0e-9_dp
246 CHARACTER(LEN=60) :: line_search_state, optimizer_task
247 INTEGER :: evaluation_count, handle, iatom, &
248 molecular_outside, npoints, unit_nr
249 INTEGER,
ALLOCATABLE :: atom_coordinate_offsets(:), &
250 bound_types(:), integer_workspace(:)
251 INTEGER,
DIMENSION(44) :: integer_state
252 LOGICAL :: evaluation_successful, fit_successful, &
254 LOGICAL,
ALLOCATABLE :: inside(:)
255 LOGICAL,
DIMENSION(4) :: logical_state
256 REAL(kind=
dp) :: best_normalized_error, max_abs_error, &
257 normalized_error, start_time
258 REAL(kind=
dp),
ALLOCATABLE :: best_grid_coordinates(:), coordinate_gradient(:), &
259 grid_coordinates(:), lower_bounds(:), points(:, :), upper_bounds(:), workspace(:)
260 REAL(kind=
dp),
DIMENSION(29) :: real_state
262 CALL timeset(
"rirs_grid_LBFGS", handle)
265 CALL pack_lbfgs_grid_coordinates(bs_env%ri_rs%atomic_grids, grid_coordinates, &
266 atom_coordinate_offsets)
267 cpassert(
SIZE(grid_coordinates) > 0)
269 ALLOCATE (best_grid_coordinates(
SIZE(grid_coordinates)), &
270 coordinate_gradient(
SIZE(grid_coordinates)), &
271 lower_bounds(
SIZE(grid_coordinates)), &
272 upper_bounds(
SIZE(grid_coordinates)), &
273 bound_types(
SIZE(grid_coordinates)), &
274 integer_workspace(3*
SIZE(grid_coordinates)), &
275 workspace(2*lbfgs_history*
SIZE(grid_coordinates) + &
276 5*
SIZE(grid_coordinates) + 11*lbfgs_history**2 + 8*lbfgs_history))
278 lower_bounds = 0.0_dp
279 upper_bounds = 0.0_dp
281 optimizer_task =
'START'
282 line_search_state =
''
283 normalized_error = huge(normalized_error)
284 coordinate_gradient = 0.0_dp
286 integer_workspace = 0
287 logical_state = .false.
292 best_normalized_error = huge(best_normalized_error)
293 best_grid_coordinates(:) = grid_coordinates
296 CALL setulb(
SIZE(grid_coordinates), lbfgs_history, grid_coordinates, &
297 lower_bounds, upper_bounds, bound_types, &
298 normalized_error, coordinate_gradient, lbfgs_factr, lbfgs_pgtol, &
299 workspace, integer_workspace, optimizer_task, -1, line_search_state, &
300 logical_state, integer_state, real_state, -1.0_dp)
301 IF (optimizer_task(1:2) ==
'FG')
THEN
302 IF (evaluation_count >= bs_env%ri_rs%grid_opt%max_iter)
EXIT
303 CALL grid_objective(grid_coordinates, atom_coordinate_offsets, bs_env, cluster_3c_int, &
304 normalized_error, coordinate_gradient, &
305 max_abs_error, evaluation_successful)
306 evaluation_count = evaluation_count + 1
307 IF (.NOT. evaluation_successful)
EXIT
308 IF (evaluation_count == 1 .AND. bs_env%unit_nr > 0)
THEN
309 WRITE (bs_env%unit_nr,
'(T2,A,T61,ES20.12)') &
310 'RI-RS grid initial normalized error', normalized_error
313 IF (.NOT. have_best .OR. normalized_error < best_normalized_error)
THEN
315 best_normalized_error = normalized_error
316 best_grid_coordinates(:) = grid_coordinates
318 ELSE IF (optimizer_task(1:5) ==
'NEW_X')
THEN
324 IF (have_best) grid_coordinates(:) = best_grid_coordinates
325 CALL grid_objective(grid_coordinates, atom_coordinate_offsets, bs_env, cluster_3c_int, &
326 normalized_error, coordinate_gradient, &
327 max_abs_error, fit_successful)
329 IF (.NOT. fit_successful) cpabort(
"RI-RS grid optimization produced no regularized fit")
331 DO iatom = 1,
SIZE(bs_env%ri_rs%atomic_grids)
332 bs_env%ri_rs%atomic_grids(iatom)%npts = &
333 SIZE(bs_env%ri_rs%atomic_grids(iatom)%raw_points, 2)
335 bs_env%ri_rs%Z_lP_exists = .false.
337 unit_nr = bs_env%unit_nr
338 IF (unit_nr > 0)
THEN
340 molecular_outside = 0
341 DO iatom = 1,
SIZE(bs_env%ri_rs%atomic_grids)
342 ALLOCATE (points(3, bs_env%ri_rs%atomic_grids(iatom)%npts), &
343 inside(bs_env%ri_rs%atomic_grids(iatom)%npts))
344 points(:, :) = bs_env%ri_rs%atomic_grids(iatom)%raw_points
346 molecular_outside = molecular_outside + count(.NOT. inside)
347 npoints = npoints +
SIZE(inside)
348 DEALLOCATE (points, inside)
350 WRITE (unit_nr,
'(T2,A,T69,F10.1,A)') &
351 'RI-RS grid optimization completed, execution time:',
m_walltime() - start_time,
' s'
352 WRITE (unit_nr,
'(T2,A,T72,ES9.1)')
'Normalized 3C error:', normalized_error
353 WRITE (unit_nr,
'(T2,A,T72,ES9.1)')
'Maximum absolute 3C error:', max_abs_error
354 WRITE (unit_nr,
'(T2,A,T69,I12,A,I0)') &
355 'Optimized points outside molecular Voronoi cells:', molecular_outside,
' / ', npoints
358 CALL timestop(handle)
359 END SUBROUTINE optimize_grid_coordinates
366 SUBROUTINE build_cluster_3c_int(bs_env, cluster_3c_int)
368 TYPE(local_cluster_3c_integrals_type), &
369 ALLOCATABLE,
INTENT(OUT) :: cluster_3c_int(:)
371 INTEGER :: handle, i_cluster_atom_j, i_cluster_atom_k, i_cluster_atom_p, iatom, iatom_j, &
372 iatom_k, iatom_p, icenter_atom, icluster_atom, ikind, ilocal_cluster, ip, &
373 n_local_clusters, nao_cluster, nri_cluster, nri_nonzero
374 INTEGER,
ALLOCATABLE :: ao_offset(:), ri_offset(:), &
377 REAL(kind=
dp) :: cluster_radius
378 REAL(kind=
dp),
ALLOCATABLE :: int_3c_nonzero(:, :, :)
385 CALL timeset(
"rirs_grid_build_clusters", handle)
387 cell => bs_env%ri_rs%cell
388 para_env => bs_env%para_env
389 particle_set => bs_env%ri_rs%particle_set
390 cluster_radius = bs_env%ri_rs%grid_opt%cutoff_atomic_cluster
391 ALLOCATE (sizes_ref_ri(bs_env%n_atom))
392 DO iatom = 1, bs_env%n_atom
393 ikind = particle_set(iatom)%atomic_kind%kind_number
394 sizes_ref_ri(iatom) = bs_env%basis_set_RI(ikind)%gto_basis_set%nsgf
396 n_local_clusters = count([(mod(icenter_atom - 1, para_env%num_pe) == para_env%mepos, &
397 icenter_atom=1, bs_env%n_atom)])
398 ALLOCATE (cluster_3c_int(n_local_clusters), &
399 ao_offset(bs_env%n_atom), ri_offset(bs_env%n_atom))
401 basis_j=bs_env%basis_set_AO, basis_k=bs_env%basis_set_AO, &
402 basis_i=bs_env%basis_set_RI)
405 DO icenter_atom = 1, bs_env%n_atom
406 IF (mod(icenter_atom - 1, para_env%num_pe) /= para_env%mepos) cycle
407 ilocal_cluster = ilocal_cluster + 1
409 cluster_3c_int(ilocal_cluster)%atom_indices)
414 DO icluster_atom = 1,
SIZE(cluster_3c_int(ilocal_cluster)%atom_indices)
415 iatom = cluster_3c_int(ilocal_cluster)%atom_indices(icluster_atom)
416 ao_offset(iatom) = nao_cluster
417 ri_offset(iatom) = nri_cluster
418 nao_cluster = nao_cluster + bs_env%sizes_AO(iatom)
419 nri_cluster = nri_cluster + sizes_ref_ri(iatom)
421 ALLOCATE (cluster_3c_int(ilocal_cluster)%Int_3c(nao_cluster, nao_cluster, nri_cluster), &
423 DO i_cluster_atom_p = 1,
SIZE(cluster_3c_int(ilocal_cluster)%atom_indices)
424 iatom_p = cluster_3c_int(ilocal_cluster)%atom_indices(i_cluster_atom_p)
425 DO i_cluster_atom_k = 1,
SIZE(cluster_3c_int(ilocal_cluster)%atom_indices)
426 iatom_k = cluster_3c_int(ilocal_cluster)%atom_indices(i_cluster_atom_k)
427 DO i_cluster_atom_j = 1,
SIZE(cluster_3c_int(ilocal_cluster)%atom_indices)
428 iatom_j = cluster_3c_int(ilocal_cluster)%atom_indices(i_cluster_atom_j)
430 integral_context, workspace, &
431 atom_j=iatom_j, atom_k=iatom_k, atom_i=iatom_p, &
432 j_offset=ao_offset(iatom_j), &
433 k_offset=ao_offset(iatom_k), &
434 i_offset=ri_offset(iatom_p), screened=screened)
439 nri_nonzero = count([(any(cluster_3c_int(ilocal_cluster)%Int_3c(:, :, ip) /= 0.0_dp), &
441 IF (nri_nonzero < nri_cluster)
THEN
442 ALLOCATE (int_3c_nonzero(nao_cluster, nao_cluster, nri_nonzero))
444 DO ip = 1, nri_cluster
445 IF (.NOT. any(cluster_3c_int(ilocal_cluster)%Int_3c(:, :, ip) /= 0.0_dp)) cycle
446 nri_nonzero = nri_nonzero + 1
447 int_3c_nonzero(:, :, nri_nonzero) = cluster_3c_int(ilocal_cluster)%Int_3c(:, :, ip)
449 CALL move_alloc(int_3c_nonzero, cluster_3c_int(ilocal_cluster)%Int_3c)
454 CALL timestop(handle)
455 END SUBROUTINE build_cluster_3c_int
466 SUBROUTINE evaluate_local_cluster(cluster_3c_int, bs_env, normalized_error, coordinate_gradient, &
467 max_abs_error, fit_successful)
468 TYPE(local_cluster_3c_integrals_type),
INTENT(IN) :: cluster_3c_int
470 REAL(kind=
dp),
INTENT(OUT) :: normalized_error
471 REAL(kind=
dp),
ALLOCATABLE,
INTENT(OUT) :: coordinate_gradient(:, :)
472 REAL(kind=
dp),
INTENT(OUT) :: max_abs_error
473 LOGICAL,
INTENT(OUT) :: fit_successful
475 INTEGER :: ao_offset, grid_point_offset, iatom, &
476 icluster_atom, ikind, n_grid_points, &
478 REAL(kind=
dp),
ALLOCATABLE :: dphi_alpha_l_mu(:, :, :), &
479 grid_points(:, :), phi_l_mu(:, :)
484 cell => bs_env%ri_rs%cell
485 particle_set => bs_env%ri_rs%particle_set
486 nao =
SIZE(cluster_3c_int%Int_3c, 1)
488 DO icluster_atom = 1,
SIZE(cluster_3c_int%atom_indices)
489 iatom = cluster_3c_int%atom_indices(icluster_atom)
490 n_grid_points = n_grid_points +
SIZE(bs_env%ri_rs%atomic_grids(iatom)%raw_points, 2)
492 ALLOCATE (grid_points(3, n_grid_points), phi_l_mu(n_grid_points, nao), &
493 dphi_alpha_l_mu(3, n_grid_points, nao), coordinate_gradient(3, n_grid_points))
495 dphi_alpha_l_mu = 0.0_dp
496 grid_point_offset = 0
497 DO icluster_atom = 1,
SIZE(cluster_3c_int%atom_indices)
498 iatom = cluster_3c_int%atom_indices(icluster_atom)
499 grid_points(:, grid_point_offset + 1:grid_point_offset + &
500 SIZE(bs_env%ri_rs%atomic_grids(iatom)%raw_points, 2)) = &
501 spread(particle_set(iatom)%r, 2, &
502 SIZE(bs_env%ri_rs%atomic_grids(iatom)%raw_points, 2)) + &
503 bs_env%ri_rs%atomic_grids(iatom)%raw_points
504 grid_point_offset = grid_point_offset +
SIZE(bs_env%ri_rs%atomic_grids(iatom)%raw_points, 2)
507 DO icluster_atom = 1,
SIZE(cluster_3c_int%atom_indices)
508 iatom = cluster_3c_int%atom_indices(icluster_atom)
509 ikind = particle_set(iatom)%atomic_kind%kind_number
510 ao_basis => bs_env%basis_set_AO(ikind)%gto_basis_set
511 nao_atom = ao_basis%nsgf
513 grid_points, ao_basis, particle_set(iatom)%r, cell, &
514 dphi=dphi_alpha_l_mu(:, :, ao_offset + 1:ao_offset + nao_atom))
515 ao_offset = ao_offset + nao_atom
517 CALL evaluate_rirs_grid_cluster(phi_l_mu, dphi_alpha_l_mu, cluster_3c_int%Int_3c, &
518 bs_env%ri_rs%tikhonov, normalized_error, coordinate_gradient, &
519 max_abs_error, fit_successful)
520 END SUBROUTINE evaluate_local_cluster
536 SUBROUTINE evaluate_rirs_grid_cluster(Phi_l_mu, dPhi_alpha_l_mu, Int_3c, tikhonov, &
537 normalized_error, coordinate_gradient, &
538 max_abs_error, fit_successful)
539 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: phi_l_mu
540 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(IN) :: dphi_alpha_l_mu, int_3c
541 REAL(kind=
dp),
INTENT(IN) :: tikhonov
542 REAL(kind=
dp),
INTENT(OUT) :: normalized_error
543 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: coordinate_gradient
544 REAL(kind=
dp),
INTENT(OUT) :: max_abs_error
545 LOGICAL,
INTENT(OUT) :: fit_successful
547 CHARACTER(len=*),
PARAMETER :: routinen =
'evaluate_rirs_grid_cluster'
548 REAL(kind=
dp),
PARAMETER :: jacobi_floor = 1.0e-16_dp
550 INTEGER :: handle, i_ao_pair, icartesian, &
551 igrid_point, imu, inu, ip, &
552 lapack_info, n_ao_pairs, &
553 n_grid_points, nao, nri, phase_handle
554 INTEGER,
ALLOCATABLE :: mu_of_pair(:), nu_of_pair(:)
555 REAL(kind=
dp) :: absolute_error, dphi_munu_l, &
556 int_3c_norm2, jacobi_scale, &
557 phi_munu_norm2, scaling_projection, &
559 REAL(kind=
dp),
ALLOCATABLE :: d_inverse_z_prime_lp(:, :), &
560 d_inverse_z_prime_times_z_prime_transpose_ll(:, :), d_ll(:, :), d_lp(:, :), &
561 de_dphi_munu_l(:, :), dphi_munu_l_scaled(:), int_3c_munu_p(:, :), jacobi_scaling(:), &
562 phi_munu_l(:, :), phi_munu_l_scaled(:, :), r_munu_p(:, :), z_prime_lp(:, :)
564 CALL timeset(routinen, handle)
566 n_grid_points =
SIZE(phi_l_mu, 1)
567 nao =
SIZE(phi_l_mu, 2)
568 nri =
SIZE(int_3c, 3)
569 n_ao_pairs = nao*(nao + 1)/2
571 cpassert(
SIZE(dphi_alpha_l_mu, 1) == 3)
572 cpassert(
SIZE(dphi_alpha_l_mu, 2) == n_grid_points)
573 cpassert(
SIZE(dphi_alpha_l_mu, 3) == nao)
574 cpassert(
SIZE(int_3c, 1) == nao)
575 cpassert(
SIZE(int_3c, 2) == nao)
576 cpassert(
SIZE(coordinate_gradient, 1) == 3)
577 cpassert(
SIZE(coordinate_gradient, 2) == n_grid_points)
578 cpassert(tikhonov >= 0.0_dp)
580 normalized_error = huge(normalized_error)
581 coordinate_gradient = 0.0_dp
582 max_abs_error = huge(max_abs_error)
583 fit_successful = .false.
584 IF (n_grid_points < 1 .OR. nri < 1)
THEN
585 CALL timestop(handle)
589 ALLOCATE (phi_munu_l(n_ao_pairs, n_grid_points), phi_munu_l_scaled(n_ao_pairs, n_grid_points), &
590 int_3c_munu_p(n_ao_pairs, nri), mu_of_pair(n_ao_pairs), nu_of_pair(n_ao_pairs), &
591 jacobi_scaling(n_grid_points))
592 CALL timeset(
"rirs_cluster_AO_products", phase_handle)
596 i_ao_pair = i_ao_pair + 1
597 mu_of_pair(i_ao_pair) = imu
598 nu_of_pair(i_ao_pair) = inu
599 symmetry_factor = sqrt(real(2 - merge(1, 0, imu == inu),
dp))
600 DO igrid_point = 1, n_grid_points
601 phi_munu_l(i_ao_pair, igrid_point) = &
602 symmetry_factor*phi_l_mu(igrid_point, imu)*phi_l_mu(igrid_point, inu)
605 int_3c_munu_p(i_ao_pair, ip) = symmetry_factor*int_3c(imu, inu, ip)
610 int_3c_norm2 = sum(int_3c_munu_p*int_3c_munu_p)
611 CALL timestop(phase_handle)
612 IF (int_3c_norm2 <= tiny(1.0_dp))
THEN
613 DEALLOCATE (phi_munu_l, phi_munu_l_scaled, int_3c_munu_p, mu_of_pair, nu_of_pair, jacobi_scaling)
614 CALL timestop(handle)
619 DO igrid_point = 1, n_grid_points
620 phi_munu_norm2 = sum(phi_munu_l(:, igrid_point)*phi_munu_l(:, igrid_point))
621 jacobi_scaling(igrid_point) = 1.0_dp/sqrt(max(phi_munu_norm2, jacobi_floor))
622 phi_munu_l_scaled(:, igrid_point) = &
623 jacobi_scaling(igrid_point)*phi_munu_l(:, igrid_point)
625 ALLOCATE (d_ll(n_grid_points, n_grid_points), d_lp(n_grid_points, nri), z_prime_lp(n_grid_points, nri))
626 CALL timeset(
"rirs_cluster_D_ll", phase_handle)
627 CALL dgemm(
'T',
'N', n_grid_points, n_grid_points, n_ao_pairs, 1.0_dp, phi_munu_l_scaled, n_ao_pairs, &
628 phi_munu_l_scaled, n_ao_pairs, 0.0_dp, d_ll, n_grid_points)
629 CALL timestop(phase_handle)
630 DO igrid_point = 1, n_grid_points
631 d_ll(igrid_point, igrid_point) = d_ll(igrid_point, igrid_point) + tikhonov
633 CALL timeset(
"rirs_cluster_d_lP", phase_handle)
634 CALL dgemm(
'T',
'N', n_grid_points, nri, n_ao_pairs, 1.0_dp, phi_munu_l_scaled, n_ao_pairs, &
635 int_3c_munu_p, n_ao_pairs, 0.0_dp, d_lp, n_grid_points)
636 CALL timestop(phase_handle)
637 CALL dpotrf(
'L', n_grid_points, d_ll, n_grid_points, lapack_info)
638 IF (lapack_info /= 0)
THEN
639 DEALLOCATE (phi_munu_l, phi_munu_l_scaled, int_3c_munu_p, d_ll, mu_of_pair, nu_of_pair, d_lp, &
640 jacobi_scaling, z_prime_lp)
641 CALL timestop(handle)
644 z_prime_lp(:, :) = d_lp
645 CALL dpotrs(
'L', n_grid_points, nri, d_ll, n_grid_points, z_prime_lp, n_grid_points, lapack_info)
647 IF (lapack_info /= 0)
THEN
648 DEALLOCATE (phi_munu_l, phi_munu_l_scaled, int_3c_munu_p, d_ll, mu_of_pair, nu_of_pair, &
649 jacobi_scaling, z_prime_lp)
650 CALL timestop(handle)
654 CALL timeset(
"rirs_cluster_residual", phase_handle)
655 ALLOCATE (r_munu_p(n_ao_pairs, nri))
656 r_munu_p(:, :) = int_3c_munu_p
658 CALL dgemm(
'N',
'N', n_ao_pairs, nri, n_grid_points, -1.0_dp, phi_munu_l_scaled, n_ao_pairs, &
659 z_prime_lp, n_grid_points, 1.0_dp, r_munu_p, n_ao_pairs)
660 normalized_error = sum(r_munu_p*r_munu_p)/int_3c_norm2
661 CALL timestop(phase_handle)
665 ALLOCATE (d_inverse_z_prime_lp(n_grid_points, nri), de_dphi_munu_l(n_ao_pairs, n_grid_points))
666 d_inverse_z_prime_lp(:, :) = z_prime_lp
667 CALL dpotrs(
'L', n_grid_points, nri, d_ll, n_grid_points, d_inverse_z_prime_lp, n_grid_points, lapack_info)
668 IF (lapack_info /= 0)
THEN
669 DEALLOCATE (phi_munu_l, phi_munu_l_scaled, int_3c_munu_p, de_dphi_munu_l, d_ll, mu_of_pair, nu_of_pair, &
670 r_munu_p, jacobi_scaling, d_inverse_z_prime_lp, z_prime_lp)
671 CALL timestop(handle)
674 CALL timeset(
"rirs_cluster_gradient_products", phase_handle)
675 CALL dgemm(
'N',
'T', n_ao_pairs, n_grid_points, nri, -2.0_dp/int_3c_norm2, r_munu_p, n_ao_pairs, &
676 z_prime_lp, n_grid_points, 0.0_dp, de_dphi_munu_l, n_ao_pairs)
677 IF (tikhonov > 0.0_dp)
THEN
678 CALL dgemm(
'N',
'T', n_ao_pairs, n_grid_points, nri, -2.0_dp*tikhonov/int_3c_norm2, r_munu_p, n_ao_pairs, &
679 d_inverse_z_prime_lp, n_grid_points, 1.0_dp, de_dphi_munu_l, n_ao_pairs)
680 ALLOCATE (d_inverse_z_prime_times_z_prime_transpose_ll(n_grid_points, n_grid_points))
681 CALL dgemm(
'N',
'T', n_grid_points, n_grid_points, nri, 1.0_dp, d_inverse_z_prime_lp, n_grid_points, &
682 z_prime_lp, n_grid_points, 0.0_dp, d_inverse_z_prime_times_z_prime_transpose_ll, n_grid_points)
683 CALL dgemm(
'N',
'N', n_ao_pairs, n_grid_points, n_grid_points, &
684 2.0_dp*tikhonov/int_3c_norm2, phi_munu_l_scaled, n_ao_pairs, &
685 d_inverse_z_prime_times_z_prime_transpose_ll, n_grid_points, 1.0_dp, de_dphi_munu_l, n_ao_pairs)
686 DEALLOCATE (d_inverse_z_prime_times_z_prime_transpose_ll)
689 CALL timestop(phase_handle)
690 CALL timeset(
"rirs_cluster_gradient_coordinates", phase_handle)
691 ALLOCATE (dphi_munu_l_scaled(n_ao_pairs))
692 DO igrid_point = 1, n_grid_points
693 jacobi_scale = jacobi_scaling(igrid_point)
694 phi_munu_norm2 = sum(phi_munu_l(:, igrid_point)*phi_munu_l(:, igrid_point))
696 DO i_ao_pair = 1, n_ao_pairs
697 imu = mu_of_pair(i_ao_pair)
698 inu = nu_of_pair(i_ao_pair)
699 symmetry_factor = sqrt(real(2 - merge(1, 0, imu == inu),
dp))
700 dphi_munu_l = symmetry_factor*( &
701 dphi_alpha_l_mu(icartesian, igrid_point, imu)* &
702 phi_l_mu(igrid_point, inu) + &
703 phi_l_mu(igrid_point, imu)* &
704 dphi_alpha_l_mu(icartesian, igrid_point, inu))
705 dphi_munu_l_scaled(i_ao_pair) = jacobi_scale*dphi_munu_l
707 IF (phi_munu_norm2 > jacobi_floor)
THEN
708 scaling_projection = &
709 dot_product(phi_munu_l(:, igrid_point), dphi_munu_l_scaled)/jacobi_scale
710 dphi_munu_l_scaled(:) = dphi_munu_l_scaled - &
711 jacobi_scale**3*phi_munu_l(:, igrid_point)*scaling_projection
713 coordinate_gradient(icartesian, igrid_point) = &
714 dot_product(de_dphi_munu_l(:, igrid_point), dphi_munu_l_scaled)
718 CALL timestop(phase_handle)
719 max_abs_error = 0.0_dp
721 DO i_ao_pair = 1, n_ao_pairs
723 sqrt(real(2 - merge(1, 0, mu_of_pair(i_ao_pair) == nu_of_pair(i_ao_pair)),
dp))
724 absolute_error = abs(r_munu_p(i_ao_pair, ip))/symmetry_factor
725 max_abs_error = max(max_abs_error, absolute_error)
729 fit_successful = .true.
730 DEALLOCATE (phi_munu_l, phi_munu_l_scaled, int_3c_munu_p, de_dphi_munu_l, dphi_munu_l_scaled, d_ll, &
731 mu_of_pair, nu_of_pair, r_munu_p, jacobi_scaling, d_inverse_z_prime_lp, z_prime_lp)
732 CALL timestop(handle)
733 END SUBROUTINE evaluate_rirs_grid_cluster
743 SUBROUTINE accumulate_atom_gradient(cluster_atoms, grids, atom_coordinate_offsets, &
744 cluster_coordinate_gradient, coordinate_gradient)
745 INTEGER,
DIMENSION(:),
INTENT(IN) :: cluster_atoms
747 INTEGER,
DIMENSION(:),
INTENT(IN) :: atom_coordinate_offsets
748 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: cluster_coordinate_gradient
749 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: coordinate_gradient
751 INTEGER :: grid_point_offset, iatom, icartesian, &
752 icluster_atom, igrid_point
754 grid_point_offset = 0
755 DO icluster_atom = 1,
SIZE(cluster_atoms)
756 iatom = cluster_atoms(icluster_atom)
757 DO igrid_point = 1,
SIZE(grids(iatom)%raw_points, 2)
759 coordinate_gradient(atom_coordinate_offsets(iatom) + 3*(igrid_point - 1) + icartesian) = &
760 coordinate_gradient(atom_coordinate_offsets(iatom) + 3*(igrid_point - 1) + icartesian) + &
761 cluster_coordinate_gradient(icartesian, grid_point_offset + igrid_point)
764 grid_point_offset = grid_point_offset +
SIZE(grids(iatom)%raw_points, 2)
766 END SUBROUTINE accumulate_atom_gradient
777 SUBROUTINE pack_lbfgs_grid_coordinates(grids, grid_coordinates, atom_coordinate_offsets)
779 REAL(kind=
dp),
ALLOCATABLE,
INTENT(OUT) :: grid_coordinates(:)
780 INTEGER,
ALLOCATABLE,
INTENT(OUT) :: atom_coordinate_offsets(:)
782 INTEGER :: atom_coordinate_count, iatom, &
785 ALLOCATE (atom_coordinate_offsets(
SIZE(grids)))
786 n_grid_coordinates = 0
787 DO iatom = 1,
SIZE(grids)
788 atom_coordinate_offsets(iatom) = n_grid_coordinates
789 n_grid_coordinates = n_grid_coordinates +
SIZE(grids(iatom)%raw_points)
791 ALLOCATE (grid_coordinates(n_grid_coordinates))
793 DO iatom = 1,
SIZE(grids)
794 atom_coordinate_count =
SIZE(grids(iatom)%raw_points)
795 grid_coordinates(atom_coordinate_offsets(iatom) + 1: &
796 atom_coordinate_offsets(iatom) + atom_coordinate_count) = &
797 reshape(grids(iatom)%raw_points, [atom_coordinate_count])
799 END SUBROUTINE pack_lbfgs_grid_coordinates
807 SUBROUTINE unpack_lbfgs_grid_coordinates(grid_coordinates, atom_coordinate_offsets, grids)
808 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: grid_coordinates
809 INTEGER,
DIMENSION(:),
INTENT(IN) :: atom_coordinate_offsets
812 INTEGER :: atom_coordinate_count, iatom
814 cpassert(
SIZE(atom_coordinate_offsets) ==
SIZE(grids))
815 DO iatom = 1,
SIZE(grids)
816 atom_coordinate_count =
SIZE(grids(iatom)%raw_points)
817 grids(iatom)%raw_points(:, :) = reshape( &
818 grid_coordinates(atom_coordinate_offsets(iatom) + 1: &
819 atom_coordinate_offsets(iatom) + &
820 atom_coordinate_count), &
821 shape(grids(iatom)%raw_points))
823 END SUBROUTINE unpack_lbfgs_grid_coordinates
static void dgemm(const char transa, const char transb, const int m, const int n, const int k, const double alpha, const double *a, const int lda, const double *b, const int ldb, const double beta, double *c, const int ldc)
Convenient wrapper to hide Fortran nature of dgemm_, swapping a and b.
Handles all functions related to the CELL.
LBFGS-B routine (version 3.0, April 25, 2011).
subroutine, public setulb(n, m, x, lower_bound, upper_bound, nbd, f, g, factr, pgtol, wa, iwa, task, iprint, csave, lsave, isave, dsave, trust_radius, spgr, iwunit)
This subroutine partitions the working arrays wa and iwa, and then uses the limited memory BFGS metho...
Initialize atom-owned RI-RS grids by Cholesky selection from Lebedev grids.
subroutine, public initialize_ri_rs_grid(bs_env)
Construct the initial RI-RS grid of every atom.
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.
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 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_basis_on_points(phi, grid_points, basis, source_position, cell, dphi, cutoff_squared)
Evaluate one explicitly supplied contracted Gaussian basis on Cartesian points.
Utility method to build 3-center integrals for small cell GW.
subroutine, public gw_3c_ws_create(ws, ctx)
Creates a per-thread 3c workspace: libint object + LIBXSMM contraction buffers.
subroutine, public build_3c_integral_block_ctx(int_3c, ctx, ws, atom_j, atom_k, atom_i, cell_j, cell_k, cell_i, j_offset, k_offset, i_offset, screened)
Computes the 3c integral block (mu(atom_j) nu(atom_k) | P(atom_i)) for ONE atom triple,...
subroutine, public gw_3c_ctx_release(ctx)
Releases the shared 3c-integral context.
subroutine, public gw_3c_ws_release(ws)
Releases a per-thread 3c workspace.
subroutine, public gw_3c_ctx_create(ctx, bs_env, potential_parameter, basis_j, basis_k, basis_i)
Build the shared 3c-integral context from the band-structure environment and explicitly supplied pote...
Defines the basic variable types.
integer, parameter, public dp
Machine interface based on Fortran 2003 and POSIX.
subroutine, public m_flush(lunit)
flushes units if the &GLOBAL flag is set accordingly
real(kind=dp) function, public m_walltime()
returns time from a real-time clock, protected against rolling early/easily
Interface to the message passing library MPI.
Define the data structure for the particle information.
Type defining parameters related to the simulation cell.
Shared read-only context for repeated 3-center integral block builds: screening parameters,...
Per-thread workspace for 3-center integral block builds: libint object + contraction buffers....
stores all the informations relevant to an mpi environment