(git:f2099e5)
Loading...
Searching...
No Matches
gw_ri_rs_grid_optimization.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 Optimize automatically initialized atom-centred RI-RS grids.
10!> \par History
11!> 09.2026 created [Jan Wilhelm]
12! **************************************************************************************************
15 USE cell_types, ONLY: cell_type
16 USE cp_lbfgs, ONLY: setulb
28 USE kinds, ONLY: dp
29 USE machine, ONLY: m_flush,&
35#include "./base/base_uses.f90"
36
37 IMPLICIT NONE
38 PRIVATE
39
40 PUBLIC :: optimize_ri_rs_grid
41
42 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'gw_ri_rs_grid_optimization'
43
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
48
49CONTAINS
50
51! **************************************************************************************************
52!> \brief Initialize Lebedev grids and subsequently optimize their grid-point coordinates.
53!> \param bs_env ...
54! **************************************************************************************************
55 SUBROUTINE optimize_ri_rs_grid(bs_env)
56 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
57
58 CHARACTER(len=*), PARAMETER :: routinen = 'optimize_ri_rs_grid'
59
60 INTEGER :: handle
61 TYPE(local_cluster_3c_integrals_type), ALLOCATABLE :: cluster_3c_int(:)
62
63 CALL timeset(routinen, handle)
64
65 ! Validate all state and user input before the initialization consumes them.
66 CALL validate_ri_rs_grid_optimization_input(bs_env)
67
68 ! setup Lebedev initial grid inside Voronoi volume, select points with Cholesky decomp.
69 CALL initialize_ri_rs_grid(bs_env)
70
71 ! Validate the initialized RI-RS state and report the start of the optimization.
72 CALL prepare_ri_rs_grid_optimization(bs_env)
73
74 ! C_A = {B: |R_A - R_B| < R_cut}; store (μν|P) for μ, ν, and P centered in C_A.
75 CALL build_cluster_3c_int(bs_env, cluster_3c_int)
76
77 ! E_A = Σ_{μνP∈C_A} [(μν|P) - Σ_{l∈G_A} ϕ_μ(r_l) ϕ_ν(r_l) Z_lP^(A)]².
78 ! Minimize E_loc(norm) = N_atom^(-1) Σ_A [E_A / Σ_{μνP∈C_A} |(μν|P)|²].
79 CALL optimize_grid_coordinates(bs_env, cluster_3c_int)
80
81 CALL timestop(handle)
82
83 END SUBROUTINE optimize_ri_rs_grid
84
85! **************************************************************************************************
86!> \brief Validate state and user input needed to initialize and optimize RI-RS grids.
87!> \param bs_env ...
88! **************************************************************************************************
89 SUBROUTINE validate_ri_rs_grid_optimization_input(bs_env)
90 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
91
92 INTEGER :: iatom, ikind
93
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))
103
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")
106 END IF
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")
109 END IF
110 IF (bs_env%ri_rs%grid_opt%max_iter < 1) THEN
111 cpabort("GRID_OPTIMIZATION%MAX_ITER must be positive")
112 END IF
113 IF (bs_env%ri_rs%tikhonov < 0.0_dp) THEN
114 cpabort("RI_RS%TIKHONOV must not be negative")
115 END IF
116
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")
125 END IF
126 END DO
127 END SUBROUTINE validate_ri_rs_grid_optimization_input
128
129! **************************************************************************************************
130!> \brief Validate initialized RI-RS state and announce the grid optimization.
131!> \param bs_env ...
132! **************************************************************************************************
133 SUBROUTINE prepare_ri_rs_grid_optimization(bs_env)
134 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
135
136 INTEGER :: iatom, unit_nr
137
138 cpassert(ALLOCATED(bs_env%ri_rs%atomic_grids))
139 cpassert(SIZE(bs_env%ri_rs%atomic_grids) == bs_env%n_atom)
140
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)
145 END DO
146
147 unit_nr = bs_env%unit_nr
148 IF (unit_nr > 0) THEN
149 WRITE (unit_nr, '(T2,A)') 'Started RI-RS grid optimization'
150 CALL m_flush(unit_nr)
151 END IF
152 END SUBROUTINE prepare_ri_rs_grid_optimization
153
154! **************************************************************************************************
155!> \brief Evaluate the normalized local objective E_loc and its gradient for one L-BFGS trial vector.
156!> \param grid_coordinates Flattened atom-relative grid coordinates.
157!> \param atom_coordinate_offsets Starting coordinate offset for each atom.
158!> \param bs_env ...
159!> \param cluster_3c_int Rank-local cluster three-centre integrals.
160!> \param normalized_error Mean normalized squared three-centre-integral error.
161!> \param coordinate_gradient Derivative of normalized_error with respect to coordinates.
162!> \param max_abs_error Largest absolute three-centre-integral error.
163!> \param fit_successful Whether every local-cluster evaluation succeeded.
164! **************************************************************************************************
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
170 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
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
177
178 INTEGER :: evaluated_cluster_count, icluster, &
179 successful_ranks
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(:, :)
184 TYPE(mp_para_env_type), POINTER :: para_env
185
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)
202 EXIT
203 END IF
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, &
208 coordinate_gradient)
209 evaluated_cluster_count = evaluated_cluster_count + 1
210 max_abs_error = &
211 max(max_abs_error, cluster_max_abs_error)
212 DEALLOCATE (cluster_coordinate_gradient)
213 END DO
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
225 RETURN
226 END IF
227 ! E_loc(norm) = (1/N_atom) Σ_A [E_A / Σ_{μνP ∈ C_A} |(μν|P)|²].
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
231
232! **************************************************************************************************
233!> \brief Drive L-BFGS, repeatedly evaluating E_loc and its gradient, and return the best trial.
234!> \param bs_env ...
235!> \param cluster_3c_int Rank-local cluster three-centre integrals.
236! **************************************************************************************************
237 SUBROUTINE optimize_grid_coordinates(bs_env, cluster_3c_int)
238 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
239 TYPE(local_cluster_3c_integrals_type), &
240 DIMENSION(:), INTENT(IN) :: cluster_3c_int
241
242 INTEGER, PARAMETER :: lbfgs_history = 7
243 REAL(kind=dp), PARAMETER :: lbfgs_factr = 0.0_dp, &
244 lbfgs_pgtol = 1.0e-9_dp
245
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, &
253 have_best
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
261
262 CALL timeset("rirs_grid_LBFGS", handle)
263 start_time = m_walltime()
264
265 CALL pack_lbfgs_grid_coordinates(bs_env%ri_rs%atomic_grids, grid_coordinates, &
266 atom_coordinate_offsets)
267 cpassert(SIZE(grid_coordinates) > 0)
268
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))
277 ! L-BFGS-B ignores lower_bounds and upper_bounds when bound_types is zero.
278 lower_bounds = 0.0_dp
279 upper_bounds = 0.0_dp
280 bound_types = 0
281 optimizer_task = 'START'
282 line_search_state = ''
283 normalized_error = huge(normalized_error)
284 coordinate_gradient = 0.0_dp
285 workspace = 0.0_dp
286 integer_workspace = 0
287 logical_state = .false.
288 integer_state = 0
289 real_state = 0.0_dp
290 evaluation_count = 0
291 have_best = .false.
292 best_normalized_error = huge(best_normalized_error)
293 best_grid_coordinates(:) = grid_coordinates
294
295 DO
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
311 CALL m_flush(bs_env%unit_nr)
312 END IF
313 IF (.NOT. have_best .OR. normalized_error < best_normalized_error) THEN
314 have_best = .true.
315 best_normalized_error = normalized_error
316 best_grid_coordinates(:) = grid_coordinates
317 END IF
318 ELSE IF (optimizer_task(1:5) == 'NEW_X') THEN
319 cycle
320 ELSE
321 EXIT
322 END IF
323 END DO
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)
328
329 IF (.NOT. fit_successful) cpabort("RI-RS grid optimization produced no regularized fit")
330
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)
334 END DO
335 bs_env%ri_rs%Z_lP_exists = .false.
336
337 unit_nr = bs_env%unit_nr
338 IF (unit_nr > 0) THEN
339 npoints = 0
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
345 CALL filter_grid_to_voronoi(points, iatom, bs_env%ri_rs%particle_set, mask=inside)
346 molecular_outside = molecular_outside + count(.NOT. inside)
347 npoints = npoints + SIZE(inside)
348 DEALLOCATE (points, inside)
349 END DO
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
356 FLUSH (unit_nr)
357 END IF
358 CALL timestop(handle)
359 END SUBROUTINE optimize_grid_coordinates
360
361! **************************************************************************************************
362!> \brief Build each C_A and store its exact (μν|P); this routine owns the integral context.
363!> \param bs_env ...
364!> \param cluster_3c_int Rank-local cluster three-centre integrals.
365! **************************************************************************************************
366 SUBROUTINE build_cluster_3c_int(bs_env, cluster_3c_int)
367 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
368 TYPE(local_cluster_3c_integrals_type), &
369 ALLOCATABLE, INTENT(OUT) :: cluster_3c_int(:)
370
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(:), &
375 sizes_ref_ri(:)
376 LOGICAL :: screened
377 REAL(kind=dp) :: cluster_radius
378 REAL(kind=dp), ALLOCATABLE :: int_3c_nonzero(:, :, :)
379 TYPE(cell_type), POINTER :: cell
380 TYPE(gw_3c_ctx_type) :: integral_context
381 TYPE(gw_3c_ws_type) :: workspace
382 TYPE(mp_para_env_type), POINTER :: para_env
383 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
384
385 CALL timeset("rirs_grid_build_clusters", handle)
386
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
395 END DO
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))
400 CALL gw_3c_ctx_create(integral_context, bs_env, bs_env%ri_metric, &
401 basis_j=bs_env%basis_set_AO, basis_k=bs_env%basis_set_AO, &
402 basis_i=bs_env%basis_set_RI)
403 CALL gw_3c_ws_create(workspace, integral_context)
404 ilocal_cluster = 0
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
408 CALL get_rirs_cluster_atoms(particle_set, cell, icenter_atom, cluster_radius, &
409 cluster_3c_int(ilocal_cluster)%atom_indices)
410 ao_offset = 0
411 ri_offset = 0
412 nao_cluster = 0
413 nri_cluster = 0
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)
420 END DO
421 ALLOCATE (cluster_3c_int(ilocal_cluster)%Int_3c(nao_cluster, nao_cluster, nri_cluster), &
422 source=0.0_dp)
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)
429 CALL build_3c_integral_block_ctx(cluster_3c_int(ilocal_cluster)%Int_3c, &
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)
435 END DO
436 END DO
437 END DO
438 ! Zero auxiliary columns contribute neither to the objective nor its derivatives.
439 nri_nonzero = count([(any(cluster_3c_int(ilocal_cluster)%Int_3c(:, :, ip) /= 0.0_dp), &
440 ip=1, nri_cluster)])
441 IF (nri_nonzero < nri_cluster) THEN
442 ALLOCATE (int_3c_nonzero(nao_cluster, nao_cluster, nri_nonzero))
443 nri_nonzero = 0
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)
448 END DO
449 CALL move_alloc(int_3c_nonzero, cluster_3c_int(ilocal_cluster)%Int_3c)
450 END IF
451 END DO
452 CALL gw_3c_ws_release(workspace)
453 CALL gw_3c_ctx_release(integral_context)
454 CALL timestop(handle)
455 END SUBROUTINE build_cluster_3c_int
456
457! **************************************************************************************************
458!> \brief Evaluate ϕ_μ(r_l) on G_A and compute the normalized local error E_A and its gradient.
459!> \param cluster_3c_int Local atom indices and exact three-centre integrals.
460!> \param bs_env ...
461!> \param normalized_error Normalized squared three-centre-integral error.
462!> \param coordinate_gradient Derivative with respect to the cluster's physical grid coordinates.
463!> \param max_abs_error Largest absolute three-centre-integral error.
464!> \param fit_successful Whether the regularized fitting equations were solved.
465! **************************************************************************************************
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
469 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
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
474
475 INTEGER :: ao_offset, grid_point_offset, iatom, &
476 icluster_atom, ikind, n_grid_points, &
477 nao, nao_atom
478 REAL(kind=dp), ALLOCATABLE :: dphi_alpha_l_mu(:, :, :), &
479 grid_points(:, :), phi_l_mu(:, :)
480 TYPE(cell_type), POINTER :: cell
481 TYPE(gto_basis_set_type), POINTER :: ao_basis
482 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
483
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)
487 n_grid_points = 0
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)
491 END DO
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))
494 phi_l_mu = 0.0_dp
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)
505 END DO
506 ao_offset = 0
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
512 CALL evaluate_ao_basis_on_points(phi_l_mu(:, ao_offset + 1:ao_offset + nao_atom), &
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
516 END DO
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
521
522! **************************************************************************************************
523!> \brief Solve the cluster-local Z_lP for one C_A and evaluate its normalized error and exact gradient.
524!>
525!> The solve applies the same column Jacobi scaling and Tikhonov parameter as the production
526!> Z_lP construction. Z_prime_lP denotes the coefficients before undoing the Jacobi scaling.
527!> \param Phi_l_mu AO values ϕ_μ(r_l), indexed (l, μ).
528!> \param dPhi_alpha_l_mu Cartesian derivatives of ϕ_μ(r_l), indexed (α, l, μ).
529!> \param Int_3c Exact three-centre integrals, indexed (mu,nu,P).
530!> \param tikhonov Tikhonov parameter used by the production RI-RS solve.
531!> \param normalized_error Normalized squared residual for this cluster.
532!> \param coordinate_gradient Analytic derivative of normalized_error with respect to r(alpha,l).
533!> \param max_abs_error Largest absolute error in an unweighted three-centre integral.
534!> \param fit_successful False if the regularized normal equations cannot be solved.
535! **************************************************************************************************
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
546
547 CHARACTER(len=*), PARAMETER :: routinen = 'evaluate_rirs_grid_cluster'
548 REAL(kind=dp), PARAMETER :: jacobi_floor = 1.0e-16_dp
549
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, &
558 symmetry_factor
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(:, :)
563
564 CALL timeset(routinen, handle)
565
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
570
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)
579
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)
586 RETURN
587 END IF
588
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)
593 i_ao_pair = 0
594 DO inu = 1, nao
595 DO imu = 1, inu
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)
603 END DO
604 DO ip = 1, nri
605 int_3c_munu_p(i_ao_pair, ip) = symmetry_factor*int_3c(imu, inu, ip)
606 END DO
607 END DO
608 END DO
609
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)
615 RETURN
616 END IF
617
618 ! D'_ll' = d_l D_ll' d_l' + λδ_ll', with d_l = 1/sqrt(D_ll).
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)
624 END DO
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
632 END DO
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)
642 RETURN
643 END IF
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)
646 DEALLOCATE (d_lp)
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)
651 RETURN
652 END IF
653
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
657 ! R_μνP = (μν|P) - Σ_l ϕ_μ(r_l) ϕ_ν(r_l) d_l Z'_lP.
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)
662
663 ! For λ>0, the residual derivative includes the response of the regularized coefficients:
664 ! dE/dϕ = [-2 R Z^T - 2λ(R Y^T - ϕ Y Z^T)] / ||Int_3c||^2.
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)
672 RETURN
673 END IF
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)
687 END IF
688
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))
695 DO icartesian = 1, 3
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
706 END DO
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
712 END IF
713 coordinate_gradient(icartesian, igrid_point) = &
714 dot_product(de_dphi_munu_l(:, igrid_point), dphi_munu_l_scaled)
715 END DO
716 END DO
717
718 CALL timestop(phase_handle)
719 max_abs_error = 0.0_dp
720 DO ip = 1, nri
721 DO i_ao_pair = 1, n_ao_pairs
722 symmetry_factor = &
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)
726 END DO
727 END DO
728
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
734
735! **************************************************************************************************
736!> \brief Sum gradient contributions from overlapping C_A into each atom-centred grid coordinate.
737!> \param cluster_atoms Atom indices in the local cluster.
738!> \param grids Atom-centred RI-RS grids.
739!> \param atom_coordinate_offsets Starting coordinate offset for each atom.
740!> \param cluster_coordinate_gradient Gradient for the cluster's physical grid points.
741!> \param coordinate_gradient Global flattened atom-relative gradient to update.
742! **************************************************************************************************
743 SUBROUTINE accumulate_atom_gradient(cluster_atoms, grids, atom_coordinate_offsets, &
744 cluster_coordinate_gradient, coordinate_gradient)
745 INTEGER, DIMENSION(:), INTENT(IN) :: cluster_atoms
746 TYPE(rirs_grid_type), DIMENSION(:), INTENT(IN) :: grids
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
750
751 INTEGER :: grid_point_offset, iatom, icartesian, &
752 icluster_atom, igrid_point
753
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)
758 DO icartesian = 1, 3
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)
762 END DO
763 END DO
764 grid_point_offset = grid_point_offset + SIZE(grids(iatom)%raw_points, 2)
765 END DO
766 END SUBROUTINE accumulate_atom_gradient
767
768! **************************************************************************************************
769!> \brief Pack all atom-centred grids into the single Cartesian vector required by L-BFGS.
770!> \param grids Atom-centred RI-RS grids.
771!> \param grid_coordinates Flattened atom-relative grid coordinates.
772!> \param atom_coordinate_offsets Starting coordinate offset for each atom.
773!>
774!> SIZE(grid_coordinates) = 3 Σ_A N_grid,A. Coordinates are ordered Cartesian component first,
775!> then grid point, then atom, matching the column-major layout of raw_points(3,N_grid,A).
776! **************************************************************************************************
777 SUBROUTINE pack_lbfgs_grid_coordinates(grids, grid_coordinates, atom_coordinate_offsets)
778 TYPE(rirs_grid_type), DIMENSION(:), INTENT(IN) :: grids
779 REAL(kind=dp), ALLOCATABLE, INTENT(OUT) :: grid_coordinates(:)
780 INTEGER, ALLOCATABLE, INTENT(OUT) :: atom_coordinate_offsets(:)
781
782 INTEGER :: atom_coordinate_count, iatom, &
783 n_grid_coordinates
784
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)
790 END DO
791 ALLOCATE (grid_coordinates(n_grid_coordinates))
792
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])
798 END DO
799 END SUBROUTINE pack_lbfgs_grid_coordinates
800
801! **************************************************************************************************
802!> \brief Restore the optimized Cartesian vector to the persistent atom-centred RI-RS grids.
803!> \param grid_coordinates Flattened atom-relative grid coordinates.
804!> \param atom_coordinate_offsets Starting coordinate offset for each atom.
805!> \param grids Atom-centred RI-RS grids to update.
806! **************************************************************************************************
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
810 TYPE(rirs_grid_type), DIMENSION(:), INTENT(INOUT) :: grids
811
812 INTEGER :: atom_coordinate_count, iatom
813
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))
822 END DO
823 END SUBROUTINE unpack_lbfgs_grid_coordinates
824
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.
Definition cell_types.F:15
LBFGS-B routine (version 3.0, April 25, 2011).
Definition cp_lbfgs.F:19
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...
Definition cp_lbfgs.F:188
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.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Machine interface based on Fortran 2003 and POSIX.
Definition machine.F:17
subroutine, public m_flush(lunit)
flushes units if the &GLOBAL flag is set accordingly
Definition machine.F:124
real(kind=dp) function, public m_walltime()
returns time from a real-time clock, protected against rolling early/easily
Definition machine.F:141
Interface to the message passing library MPI.
Define the data structure for the particle information.
Type defining parameters related to the simulation cell.
Definition cell_types.F:60
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