24 USE ieee_arithmetic,
ONLY: ieee_is_finite
35#include "./base/base_uses.f90"
41 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'qs_scf_oda'
42 CHARACTER(len=*),
PARAMETER,
PRIVATE :: status_no_acceptable =
"NO_ACCEPTABLE", &
43 status_non_descent =
"NON_DESCENT", &
44 status_nonfinite =
"NONFINITE", &
45 status_success =
"SUCCESS"
67 SUBROUTINE qs_scf_oda_apply(qs_env, scf_env, rho, ks_env, base_fock, matrix_ks, rho_ao, base_energy, &
68 predictor_lambda, predictor_valid, applied, state_evaluated, &
75 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
INTENT(IN) :: base_fock
76 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_ks, rho_ao
78 REAL(kind=
dp),
INTENT(INOUT) :: predictor_lambda
79 LOGICAL,
INTENT(INOUT) :: predictor_valid
80 LOGICAL,
INTENT(OUT) :: applied, state_evaluated
83 CHARACTER(LEN=*),
PARAMETER :: routinen =
'qs_scf_oda_apply'
84 INTEGER,
PARAMETER :: max_backtracking = 9
85 REAL(kind=
dp),
PARAMETER :: armijo_factor = 1.0e-4_dp, initial_lambda = 0.5_dp, &
86 maximum_backtrack_fraction = 0.8_dp, minimum_backtrack_fraction = 0.1_dp, &
87 minimum_lambda = 1.0_dp/1024.0_dp, predictor_growth = 1.5_dp
89 CHARACTER(len=15) :: status
90 CHARACTER(len=default_string_length) :: name
91 INTEGER :: evaluations, handle, i, icell, ispin
92 LOGICAL :: model_valid, trial_accepted
93 REAL(kind=
dp) :: current_lambda, gradient0, gradient1, &
94 lambda, proposed_fraction, &
95 proposed_lambda, trial_energy, &
97 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: direction
100 CALL timeset(routinen, handle)
103 NULLIFY (direction, energy)
107 state_evaluated = .false.
109 trial_energy = base_energy%total
113 status = status_nonfinite
115 IF (predictor_valid .AND. ieee_is_finite(predictor_lambda) .AND. &
116 predictor_lambda >= minimum_lambda .AND. predictor_lambda <= 1.0_dp)
THEN
117 trial_lambda = predictor_lambda
119 trial_lambda = initial_lambda
121 predictor_lambda = 1.0_dp
122 predictor_valid = .false.
124 cpassert(
ASSOCIATED(energy))
125 evaluated_energy = base_energy
126 cpassert(
ASSOCIATED(scf_env%p_mix_new))
127 cpassert(
SIZE(scf_env%p_mix_new, 1) ==
SIZE(rho_ao, 1))
128 cpassert(
SIZE(scf_env%p_mix_new, 2) ==
SIZE(rho_ao, 2))
129 cpassert(
SIZE(base_fock, 1) ==
SIZE(rho_ao, 1))
130 cpassert(
SIZE(base_fock, 2) ==
SIZE(rho_ao, 2))
131 cpassert(
SIZE(matrix_ks, 1) ==
SIZE(rho_ao, 1))
132 cpassert(
SIZE(matrix_ks, 2) ==
SIZE(rho_ao, 2))
135 CALL create_direction(scf_env%p_mix_new, rho_ao, direction)
136 CALL directional_derivative(base_fock, direction, gradient0)
137 IF (.NOT. ieee_is_finite(gradient0))
EXIT oda_search
138 IF (gradient0 >= 0.0_dp)
THEN
139 status = status_non_descent
143 DO i = 0, max_backtracking
144 IF (trial_lambda < minimum_lambda)
EXIT
145 CALL set_trial_density(rho_ao, scf_env%p_mix_new, direction, trial_lambda)
146 CALL evaluate_trial(qs_env, scf_env, rho, ks_env)
147 evaluations = evaluations + 1
148 current_lambda = trial_lambda
149 trial_energy = energy%total
150 CALL directional_derivative(matrix_ks, direction, gradient1)
151 trial_accepted = .false.
152 IF (ieee_is_finite(gradient1))
THEN
153 trial_accepted = armijo_satisfied(base_energy%total, gradient0, trial_lambda, &
154 trial_energy, armijo_factor)
156 IF (trial_accepted)
THEN
158 lambda = trial_lambda
159 IF (gradient1 < 0.0_dp)
THEN
160 predictor_lambda = min(1.0_dp, 2.0_dp*lambda)
162 predictor_lambda = min(1.0_dp, predictor_growth*lambda)
164 predictor_valid = .true.
165 status = status_success
171 CALL cubic_step(base_energy%total, current_lambda*gradient0, trial_energy, &
172 current_lambda*gradient1, proposed_fraction, model_valid)
173 IF (model_valid)
THEN
174 proposed_lambda = current_lambda*proposed_fraction
175 trial_lambda = min(maximum_backtrack_fraction*current_lambda, &
176 max(minimum_backtrack_fraction*current_lambda, proposed_lambda))
178 trial_lambda = 0.5_dp*current_lambda
184 IF (abs(current_lambda - 1.0_dp) > 64.0_dp*epsilon(1.0_dp))
THEN
185 CALL set_trial_density(rho_ao, scf_env%p_mix_new, direction, 1.0_dp)
186 CALL evaluate_trial(qs_env, scf_env, rho, ks_env)
187 evaluations = evaluations + 1
188 CALL directional_derivative(matrix_ks, direction, gradient1)
191 status = status_no_acceptable
194 IF (evaluations > 0)
THEN
195 trial_energy = energy%total
196 evaluated_energy = energy
197 state_evaluated = .true.
201 DO icell = 1,
SIZE(rho_ao, 2)
202 DO ispin = 1,
SIZE(rho_ao, 1)
203 CALL dbcsr_get_info(scf_env%p_mix_new(ispin, icell)%matrix, name=name)
204 CALL dbcsr_copy(scf_env%p_mix_new(ispin, icell)%matrix, rho_ao(ispin, icell)%matrix, name=name)
208 scf_env%oda_lambda = lambda
209 scf_env%oda_energy = trial_energy
210 scf_env%oda_gradient0 = gradient0
211 scf_env%oda_gradient1 = gradient1
212 scf_env%oda_evaluations = evaluations
213 scf_env%oda_status = status
219 CALL timestop(handle)
232 PURE SUBROUTINE cubic_step(energy0, gradient0, energy1, gradient1, lambda, valid)
234 REAL(kind=dp),
INTENT(IN) :: energy0, gradient0, energy1, gradient1
235 REAL(kind=dp),
INTENT(OUT) :: lambda
236 LOGICAL,
INTENT(OUT) :: valid
239 REAL(kind=dp) :: a, b, best_value, discriminant, energy_delta, model_value, q, quadratic_a, &
240 quadratic_b, quadratic_c, root, scale, sqrt_discriminant, tolerance
241 REAL(kind=dp),
DIMENSION(2) :: roots
245 IF (.NOT. ieee_is_finite(energy0) .OR. .NOT. ieee_is_finite(gradient0) .OR. &
246 .NOT. ieee_is_finite(energy1) .OR. .NOT. ieee_is_finite(gradient1))
RETURN
248 energy_delta = energy1 - energy0
249 scale = max(1.0_dp, abs(energy_delta), abs(gradient0), abs(gradient1))
250 tolerance = 128.0_dp*epsilon(1.0_dp)*scale
251 IF (gradient0 >= -tolerance)
RETURN
254 a = 3.0_dp*energy_delta - 2.0_dp*gradient0 - gradient1
255 b = gradient0 + gradient1 - 2.0_dp*energy_delta
256 IF (.NOT. ieee_is_finite(a) .OR. .NOT. ieee_is_finite(b))
RETURN
258 quadratic_a = 3.0_dp*b
259 quadratic_b = 2.0_dp*a
260 quadratic_c = gradient0
261 IF (.NOT. ieee_is_finite(quadratic_a) .OR. .NOT. ieee_is_finite(quadratic_b) .OR. &
262 .NOT. ieee_is_finite(quadratic_c))
RETURN
266 IF (abs(quadratic_a) <= tolerance)
THEN
267 IF (abs(quadratic_b) > tolerance)
THEN
269 roots(1) = -quadratic_c/quadratic_b
272 discriminant = quadratic_b*quadratic_b - 4.0_dp*quadratic_a*quadratic_c
273 IF (.NOT. ieee_is_finite(discriminant))
RETURN
274 IF (discriminant >= -tolerance*scale)
THEN
275 discriminant = max(0.0_dp, discriminant)
276 sqrt_discriminant = sqrt(discriminant)
277 q = -0.5_dp*(quadratic_b + sign(sqrt_discriminant, quadratic_b))
278 IF (abs(q) > tolerance)
THEN
280 roots(1) = q/quadratic_a
281 roots(2) = quadratic_c/q
284 roots(1) = -quadratic_b/(2.0_dp*quadratic_a)
289 best_value = energy_delta
292 IF (.NOT. ieee_is_finite(root)) cycle
293 IF (root <= 0.0_dp .OR. root >= 1.0_dp) cycle
294 model_value = gradient0*root + a*root*root + b*root*root*root
295 IF (.NOT. ieee_is_finite(model_value)) cycle
296 IF (model_value < best_value - tolerance)
THEN
297 best_value = model_value
302 lambda = min(1.0_dp, max(0.0_dp, lambda))
305 END SUBROUTINE cubic_step
316 PURE LOGICAL FUNCTION armijo_satisfied(energy0, gradient0, lambda, trial_energy, &
317 armijo_factor)
RESULT(satisfied)
319 REAL(kind=dp),
INTENT(IN) :: energy0, gradient0, lambda, &
320 trial_energy, armijo_factor
322 REAL(kind=dp) :: tolerance
325 IF (.NOT. ieee_is_finite(energy0) .OR. .NOT. ieee_is_finite(gradient0) .OR. &
326 .NOT. ieee_is_finite(lambda) .OR. .NOT. ieee_is_finite(trial_energy) .OR. &
327 .NOT. ieee_is_finite(armijo_factor))
RETURN
328 IF (gradient0 >= 0.0_dp .OR. lambda <= 0.0_dp .OR. lambda > 1.0_dp .OR. &
329 armijo_factor <= 0.0_dp .OR. armijo_factor >= 1.0_dp)
RETURN
331 tolerance = 128.0_dp*epsilon(1.0_dp)*max(1.0_dp, abs(energy0), abs(trial_energy))
332 satisfied = trial_energy <= energy0 + armijo_factor*lambda*gradient0 + tolerance
334 END FUNCTION armijo_satisfied
342 SUBROUTINE create_direction(endpoint, base, direction)
344 TYPE(dbcsr_p_type),
DIMENSION(:, :),
INTENT(IN) :: endpoint, base
345 TYPE(dbcsr_p_type),
DIMENSION(:, :),
POINTER :: direction
347 INTEGER :: icell, ispin
349 CALL dbcsr_allocate_matrix_set(direction,
SIZE(endpoint, 1),
SIZE(endpoint, 2))
350 DO icell = 1,
SIZE(endpoint, 2)
351 DO ispin = 1,
SIZE(endpoint, 1)
352 ALLOCATE (direction(ispin, icell)%matrix)
353 CALL dbcsr_create(direction(ispin, icell)%matrix, template=endpoint(ispin, icell)%matrix, &
354 name=
"ODA DENSITY DIRECTION")
355 CALL dbcsr_copy(direction(ispin, icell)%matrix, endpoint(ispin, icell)%matrix)
356 CALL dbcsr_add(direction(ispin, icell)%matrix, base(ispin, icell)%matrix, &
357 alpha_scalar=1.0_dp, beta_scalar=-1.0_dp)
361 END SUBROUTINE create_direction
370 SUBROUTINE set_trial_density(density, endpoint, direction, lambda)
372 TYPE(dbcsr_p_type),
DIMENSION(:, :),
INTENT(INOUT) :: density
373 TYPE(dbcsr_p_type),
DIMENSION(:, :),
INTENT(IN) :: endpoint, direction
374 REAL(kind=dp),
INTENT(IN) :: lambda
376 CHARACTER(len=default_string_length) :: name
377 INTEGER :: icell, ispin
379 DO icell = 1,
SIZE(density, 2)
380 DO ispin = 1,
SIZE(density, 1)
381 CALL dbcsr_get_info(density(ispin, icell)%matrix, name=name)
382 CALL dbcsr_copy(density(ispin, icell)%matrix, endpoint(ispin, icell)%matrix, name=name)
383 IF (lambda /= 1.0_dp)
THEN
384 CALL dbcsr_add(density(ispin, icell)%matrix, direction(ispin, icell)%matrix, &
385 alpha_scalar=1.0_dp, beta_scalar=lambda - 1.0_dp)
390 END SUBROUTINE set_trial_density
398 SUBROUTINE directional_derivative(fock, direction, derivative)
400 TYPE(dbcsr_p_type),
DIMENSION(:, :),
INTENT(IN) :: fock, direction
401 REAL(kind=dp),
INTENT(OUT) :: derivative
403 INTEGER :: icell, ispin
404 REAL(kind=dp) :: contribution
409 DO icell = 1,
SIZE(fock, 2)
410 DO ispin = 1,
SIZE(fock, 1)
411 CALL dbcsr_dot(fock(ispin, icell)%matrix, direction(ispin, icell)%matrix, contribution)
412 derivative = derivative + contribution
416 END SUBROUTINE directional_derivative
425 SUBROUTINE evaluate_trial(qs_env, scf_env, rho, ks_env)
427 TYPE(qs_environment_type),
POINTER :: qs_env
428 TYPE(qs_scf_env_type),
POINTER :: scf_env
429 TYPE(qs_rho_type),
POINTER :: rho
430 TYPE(qs_ks_env_type),
POINTER :: ks_env
432 CALL qs_scf_rho_update(rho, qs_env, scf_env, ks_env, mix_rho=.false.)
433 CALL qs_ks_update_qs_env(qs_env, just_energy=.false., calculate_forces=.false., &
434 print_active=.false.)
436 END SUBROUTINE evaluate_trial
collects all references to literature in CP2K as new algorithms / method are included from literature...
integer, save, public cances2000
integer, save, public herbst2022
subroutine, public dbcsr_copy(matrix_b, matrix_a, name, keep_sparsity, keep_imaginary)
...
subroutine, public dbcsr_get_info(matrix, nblkrows_total, nblkcols_total, nfullrows_total, nfullcols_total, nblkrows_local, nblkcols_local, nfullrows_local, nfullcols_local, my_prow, my_pcol, local_rows, local_cols, proc_row_dist, proc_col_dist, row_blk_size, col_blk_size, row_blk_offset, col_blk_offset, distribution, name, matrix_type, group)
...
subroutine, public dbcsr_add(matrix_a, matrix_b, alpha_scalar, beta_scalar)
...
subroutine, public dbcsr_dot(matrix_a, matrix_b, trace)
Computes the dot product of two matrices, also known as the trace of their matrix product.
DBCSR operations in CP2K.
Defines the basic variable types.
integer, parameter, public dp
integer, parameter, public default_string_length
subroutine, public get_qs_env(qs_env, atomic_kind_set, qs_kind_set, cell, super_cell, cell_ref, use_ref_cell, kpoints, dft_control, mos, sab_orb, sab_all, qmmm, qmmm_periodic, mimic, sac_ae, sac_ppl, sac_lri, sap_ppnl, sab_vdw, sab_scp, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, sab_xb, sab_xtb_pp, sab_xtb_nonbond, sab_almo, sab_kp, sab_kp_nosym, sab_cneo, particle_set, energy, force, matrix_h, matrix_h_im, matrix_ks, matrix_ks_im, matrix_vxc, run_rtp, rtp, matrix_h_kp, matrix_h_im_kp, matrix_ks_kp, matrix_ks_im_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, matrix_w_kp, matrix_s_ri_aux_kp, matrix_s, matrix_s_ri_aux, matrix_w, matrix_p_mp2, matrix_p_mp2_admm, matrix_vhxc, rho, rho_xc, pw_env, ewald_env, ewald_pw, active_space, mpools, input, para_env, blacs_env, scf_control, rel_control, kinetic, qs_charges, vppl, xcint_weights, rho_core, rho_nlcc, rho_nlcc_g, ks_env, ks_qmmm_env, wf_history, scf_env, local_particles, local_molecules, distribution_2d, dbcsr_dist, molecule_kind_set, molecule_set, subsys, cp_subsys, oce, local_rho_set, rho_atom_set, task_list, task_list_soft, rho0_atom_set, rho0_mpole, rhoz_set, rhoz_cneo_set, ecoul_1c, rho0_s_rs, rho0_s_gs, rhoz_cneo_s_rs, rhoz_cneo_s_gs, do_kpoints, has_unit_metric, requires_mo_derivs, mo_derivs, mo_loc_history, nkind, natom, nelectron_total, nelectron_spin, efield, neighbor_list_id, linres_control, xas_env, virial, cp_ddapc_env, cp_ddapc_ewald, outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, results, se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, lri_env, lri_density, exstate_env, ec_env, harris_env, dispersion_env, gcp_env, vee, rho_external, external_vxc, mask, mp2_env, bs_env, kg_env, wanniercentres, atprop, ls_scf_env, do_transport, transport_env, v_hartree_rspace, s_mstruct_changed, rho_changed, potential_changed, forces_up_to_date, mscfg_env, almo_scf_env, gradient_history, variable_history, embed_pot, spin_embed_pot, polar_env, mos_last_converged, eeq, rhs, do_rixs, tb_tblite)
Get the QUICKSTEP environment.
routines that build the Kohn-Sham matrix (i.e calculate the coulomb and xc parts
subroutine, public qs_ks_update_qs_env(qs_env, calculate_forces, just_energy, print_active)
updates the Kohn Sham matrix of the given qs_env (facility method)
superstucture that hold various representations of the density and keeps track of which ones are vali...
Utility routines for qs_scf.
subroutine, public qs_scf_rho_update(rho, qs_env, scf_env, ks_env, mix_rho)
Performs the updates rho (takes care of mixing as well).
Safeguarded optimal damping of raw Roothaan SCF steps.
subroutine, public qs_scf_oda_apply(qs_env, scf_env, rho, ks_env, base_fock, matrix_ks, rho_ao, base_energy, predictor_lambda, predictor_valid, applied, state_evaluated, evaluated_energy)
Apply a safeguarded ODA line search to an already diagonalized raw SCF endpoint.
module that contains the definitions of the scf types
calculation environment to calculate the ks matrix, holds all the needed vars. assumes that the core ...
keeps the density in various representations, keeping track of which ones are valid.