26#include "./base/base_uses.f90"
46 LOGICAL :: do_mixing, legacy_alpha_explicit, &
47 mixing_alpha_explicit, mixing_explicit
48 REAL(kind=
dp) :: legacy_alpha
51 NULLIFY (mixing_section)
54 explicit=legacy_alpha_explicit)
55 IF (legacy_alpha < 0.0_dp .OR. legacy_alpha > 1.0_dp)
THEN
56 cpabort(
"Specify an active-space damping factor between 0 and 1.")
63 active_space_env%as_mixing_dim = 0
64 active_space_env%as_mixing_iter = 0
66 IF (.NOT. do_mixing)
THEN
68 active_space_env%alpha = 1.0_dp
73 i_val=active_space_env%as_mixing_method)
75 SELECT CASE (active_space_env%as_mixing_method)
77 active_space_env%alpha = 1.0_dp
82 CALL cp_abort(__location__, &
83 "ACTIVE_SPACE%MIXING%METHOD KERKER_MIXING is not supported. "// &
84 "The active-space density lives in the active MO subspace, "// &
87 cpabort(
"ACTIVE_SPACE%MIXING%METHOD MULTISECANT_MIXING is not yet supported.")
89 cpabort(
"Unknown ACTIVE_SPACE%MIXING%METHOD.")
92 IF (
ASSOCIATED(active_space_env%as_mixing_store))
THEN
93 cpabort(
"Active-space mixing storage already initialized.")
95 ALLOCATE (active_space_env%as_mixing_store)
97 active_space_env%as_mixing_method, ecut=0.0_dp)
100 IF ((legacy_alpha_explicit .AND. (.NOT. mixing_alpha_explicit)) .OR. &
101 ((.NOT. mixing_explicit) .AND. (.NOT. mixing_alpha_explicit)))
THEN
102 active_space_env%as_mixing_store%alpha = legacy_alpha
104 IF (active_space_env%as_mixing_store%alpha < 0.0_dp .OR. &
105 active_space_env%as_mixing_store%alpha > 1.0_dp)
THEN
106 cpabort(
"Specify an active-space mixing ALPHA between 0 and 1.")
108 IF (active_space_env%as_mixing_store%nbuffer < 1 .AND. &
110 cpabort(
"ACTIVE_SPACE%MIXING%NBUFFER has to be positive.")
113 active_space_env%alpha = active_space_env%as_mixing_store%alpha
124 CHARACTER(len=15) :: label
126 SELECT CASE (active_space_env%as_mixing_method)
138 IF (
ASSOCIATED(active_space_env%as_mixing_store))
THEN
139 IF (active_space_env%as_mixing_iter > 0 .AND. &
140 len_trim(active_space_env%as_mixing_store%iter_method) > 0)
THEN
141 label = active_space_env%as_mixing_store%iter_method
151 SUBROUTINE release_active_mixing_history(active_space_env)
154 IF (
ASSOCIATED(active_space_env%as_mix_r_old))
THEN
155 DEALLOCATE (active_space_env%as_mix_r_old)
157 IF (
ASSOCIATED(active_space_env%as_mix_weight))
THEN
158 DEALLOCATE (active_space_env%as_mix_weight)
160 IF (
ASSOCIATED(active_space_env%as_mix_x_old))
THEN
161 DEALLOCATE (active_space_env%as_mix_x_old)
163 IF (
ASSOCIATED(active_space_env%as_mix_r_buffer))
THEN
164 DEALLOCATE (active_space_env%as_mix_r_buffer)
166 IF (
ASSOCIATED(active_space_env%as_mix_x_buffer))
THEN
167 DEALLOCATE (active_space_env%as_mix_x_buffer)
169 active_space_env%as_mixing_dim = 0
171 END SUBROUTINE release_active_mixing_history
178 SUBROUTINE ensure_active_mixing_history(active_space_env, ndim)
180 INTEGER,
INTENT(IN) :: ndim
185 IF (.NOT.
ASSOCIATED(active_space_env%as_mixing_store))
RETURN
188 mixing_store => active_space_env%as_mixing_store
189 nbuffer = mixing_store%nbuffer
190 IF (nbuffer < 1) cpabort(
"ACTIVE_SPACE%MIXING%NBUFFER has to be positive.")
192 IF (active_space_env%as_mixing_dim == ndim .AND. &
193 ASSOCIATED(active_space_env%as_mix_r_buffer))
RETURN
195 CALL release_active_mixing_history(active_space_env)
197 active_space_env%as_mixing_dim = ndim
198 ALLOCATE (active_space_env%as_mix_r_old(ndim))
199 ALLOCATE (active_space_env%as_mix_weight(nbuffer))
200 ALLOCATE (active_space_env%as_mix_x_old(ndim))
201 ALLOCATE (active_space_env%as_mix_r_buffer(nbuffer, ndim))
202 ALLOCATE (active_space_env%as_mix_x_buffer(nbuffer, ndim))
204 active_space_env%as_mix_r_old = 0.0_dp
205 active_space_env%as_mix_weight = 1.0_dp
206 active_space_env%as_mix_x_old = 0.0_dp
207 active_space_env%as_mix_r_buffer = 0.0_dp
208 active_space_env%as_mix_x_buffer = 0.0_dp
209 mixing_store%ncall = 0
211 END SUBROUTINE ensure_active_mixing_history
220 SUBROUTINE active_space_direct_mix(p_old, p_solver, alpha, p_mixed)
221 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: p_old, p_solver
222 REAL(kind=
dp),
INTENT(IN) :: alpha
223 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: p_mixed
225 p_mixed = p_old + alpha*(p_solver - p_old)
227 END SUBROUTINE active_space_direct_mix
236 SUBROUTINE active_space_pulay_mixing(active_space_env, p_old, p_solver, p_mixed)
238 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: p_old, p_solver
239 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: p_mixed
241 INTEGER :: i, ib, ibb, j, nb, nbuffer, ndim
242 REAL(kind=
dp) :: inv_err, norm_c_inv, res_norm
243 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: alpha_c, p_diis
244 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: c, c_inv
248 CALL ensure_active_mixing_history(active_space_env, ndim)
249 mixing_store => active_space_env%as_mixing_store
250 nbuffer = mixing_store%nbuffer
252 ib =
modulo(mixing_store%ncall, nbuffer) + 1
253 mixing_store%ncall = mixing_store%ncall + 1
254 nb = min(mixing_store%ncall, nbuffer)
255 ibb =
modulo(mixing_store%ncall, nbuffer) + 1
257 active_space_env%as_mix_x_buffer(ib, :) = p_old
258 active_space_env%as_mix_r_buffer(ib, :) = p_solver - p_old
259 res_norm = sqrt(dot_product(active_space_env%as_mix_r_buffer(ib, :), &
260 active_space_env%as_mix_r_buffer(ib, :)))
262 IF (nb == 1 .OR. res_norm < 1.e-14_dp)
THEN
263 CALL active_space_direct_mix(p_old, p_solver, mixing_store%alpha, p_mixed)
266 ALLOCATE (c_inv(nb, nb))
267 ALLOCATE (alpha_c(nb))
268 ALLOCATE (p_diis(ndim))
273 c(j, i) = dot_product(active_space_env%as_mix_r_buffer(i, :), &
274 active_space_env%as_mix_r_buffer(j, :))
280 norm_c_inv = sum(c_inv)
281 IF (abs(norm_c_inv) < 1.e-14_dp)
THEN
282 CALL active_space_direct_mix(p_old, p_solver, mixing_store%alpha, p_mixed)
285 alpha_c(i) = sum(c_inv(:, i))/norm_c_inv
290 p_diis(:) = p_diis(:) + alpha_c(i)*(active_space_env%as_mix_x_buffer(i, :) + &
291 mixing_store%pulay_beta*active_space_env%as_mix_r_buffer(i, :))
293 IF (mixing_store%pulay_alpha > 0.0_dp)
THEN
294 p_mixed = mixing_store%pulay_alpha*p_solver + &
295 (1.0_dp - mixing_store%pulay_alpha)*p_diis
307 active_space_env%as_mix_x_buffer(ibb, :) = p_mixed
308 mixing_store%iter_method =
"Pulay"
310 END SUBROUTINE active_space_pulay_mixing
320 SUBROUTINE active_space_broyden_mixing(active_space_env, p_old, p_solver, p_mixed, modified)
322 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: p_old, p_solver
323 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: p_mixed
324 LOGICAL,
INTENT(IN) :: modified
326 INTEGER :: ib, j, k, nb, nbuffer, ndim
327 LOGICAL :: can_update
328 REAL(kind=
dp) :: delta_norm, inv_err, res_norm, weight
329 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: c, g, p_res
330 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: a, b
334 CALL ensure_active_mixing_history(active_space_env, ndim)
335 mixing_store => active_space_env%as_mixing_store
336 nbuffer = mixing_store%nbuffer
338 ALLOCATE (p_res(ndim))
339 p_res(:) = p_solver(:) - p_old(:)
340 res_norm = sqrt(dot_product(p_res, p_res))
342 mixing_store%ncall = mixing_store%ncall + 1
343 IF (mixing_store%ncall == 1)
THEN
344 CALL active_space_direct_mix(p_old, p_solver, mixing_store%alpha, p_mixed)
345 active_space_env%as_mix_x_old = p_old
346 active_space_env%as_mix_r_old = p_res
348 mixing_store%iter_method =
"MBroy"
350 mixing_store%iter_method =
"Broy."
356 nb = min(mixing_store%ncall - 1, nbuffer)
357 ib =
modulo(mixing_store%ncall - 2, nbuffer) + 1
359 active_space_env%as_mix_r_buffer(ib, :) = p_res - active_space_env%as_mix_r_old
360 active_space_env%as_mix_x_buffer(ib, :) = p_old - active_space_env%as_mix_x_old
361 delta_norm = sqrt(dot_product(active_space_env%as_mix_r_buffer(ib, :), &
362 active_space_env%as_mix_r_buffer(ib, :)))
363 can_update = res_norm > 1.e-14_dp .AND. delta_norm > 1.e-14_dp
366 active_space_env%as_mix_r_buffer(ib, :) = active_space_env%as_mix_r_buffer(ib, :)/delta_norm
367 active_space_env%as_mix_x_buffer(ib, :) = active_space_env%as_mix_x_buffer(ib, :)/delta_norm + &
368 mixing_store%alpha*active_space_env%as_mix_r_buffer(ib, :)
371 IF (res_norm > (mixing_store%wc/mixing_store%wmax))
THEN
372 active_space_env%as_mix_weight(ib) = mixing_store%wc/res_norm
374 active_space_env%as_mix_weight(ib) = mixing_store%wmax
376 active_space_env%as_mix_weight(ib) = max(1.0_dp, active_space_env%as_mix_weight(ib))
388 a(k, j) = dot_product(active_space_env%as_mix_r_buffer(j, :), &
389 active_space_env%as_mix_r_buffer(k, :))
395 c(j) = dot_product(active_space_env%as_mix_r_buffer(j, :), p_res)
397 c(j) = active_space_env%as_mix_weight(j)*c(j)
399 a(k, j) = active_space_env%as_mix_weight(k)* &
400 active_space_env%as_mix_weight(j)*a(k, j)
402 a(j, j) = mixing_store%broy_w0*mixing_store%broy_w0 + a(j, j)
404 a(j, j) = mixing_store%broy_w0 + a(j, j)
412 g(j) = g(j) + b(k, j)*c(k)
416 CALL active_space_direct_mix(p_old, p_solver, mixing_store%alpha, p_mixed)
419 IF (modified) weight = active_space_env%as_mix_weight(j)
420 p_mixed = p_mixed - weight*g(j)*active_space_env%as_mix_x_buffer(j, :)
428 active_space_env%as_mix_r_buffer(ib, :) = 0.0_dp
429 active_space_env%as_mix_x_buffer(ib, :) = 0.0_dp
430 CALL active_space_direct_mix(p_old, p_solver, mixing_store%alpha, p_mixed)
433 active_space_env%as_mix_x_old = p_old
434 active_space_env%as_mix_r_old = p_res
436 mixing_store%iter_method =
"MBroy"
438 mixing_store%iter_method =
"Broy."
443 END SUBROUTINE active_space_broyden_mixing
452 SUBROUTINE mix_active_density_vector(active_space_env, p_old, p_solver, p_mixed)
454 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: p_old, p_solver
455 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: p_mixed
457 INTEGER :: active_mix_iter
460 IF (active_space_env%as_mixing_method ==
no_mixing_nr .OR. &
461 .NOT.
ASSOCIATED(active_space_env%as_mixing_store))
THEN
466 mixing_store => active_space_env%as_mixing_store
467 active_space_env%as_mixing_iter = active_space_env%as_mixing_iter + 1
469 IF (active_space_env%as_mixing_iter <= mixing_store%nskip_mixing)
THEN
471 mixing_store%iter_method =
"NoMix"
475 active_mix_iter = active_space_env%as_mixing_iter - mixing_store%nskip_mixing
477 active_mix_iter <= mixing_store%n_simple_mix)
THEN
478 CALL active_space_direct_mix(p_old, p_solver, mixing_store%alpha, p_mixed)
479 mixing_store%iter_method =
"P_Mix"
483 SELECT CASE (active_space_env%as_mixing_method)
485 CALL active_space_pulay_mixing(active_space_env, p_old, p_solver, p_mixed)
487 CALL active_space_broyden_mixing(active_space_env, p_old, p_solver, p_mixed, .false.)
489 CALL active_space_broyden_mixing(active_space_env, p_old, p_solver, p_mixed, .true.)
491 cpabort(
"Unsupported ACTIVE_SPACE%MIXING%METHOD.")
494 END SUBROUTINE mix_active_density_vector
504 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: p_act_mo_a
506 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN),
OPTIONAL :: p_act_mo_b
508 INTEGER :: i1, i2,
idx, ispin, m1, m2, nact2, &
510 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: p_mixed, p_old, p_solver
513 nmo_active = active_space_env%nmo_active
514 nact2 = nmo_active*nmo_active
515 nspins = active_space_env%nspins
516 cpassert(
SIZE(p_act_mo_a) == nact2)
517 IF (nspins == 2)
THEN
518 IF (.NOT.
PRESENT(p_act_mo_b)) cpabort(
"Missing beta active-space density.")
519 cpassert(
SIZE(p_act_mo_b) == nact2)
522 ALLOCATE (p_mixed(nspins*nact2))
523 ALLOCATE (p_old(nspins*nact2))
524 ALLOCATE (p_solver(nspins*nact2))
526 p_solver(1:nact2) = p_act_mo_a
527 IF (nspins == 2)
THEN
528 p_solver(nact2 + 1:2*nact2) = p_act_mo_b
533 p_active => active_space_env%p_active(ispin)
534 DO i1 = 1, nmo_active
535 m1 = active_space_env%active_orbitals(i1, ispin)
536 DO i2 = 1, nmo_active
538 m2 = active_space_env%active_orbitals(i2, ispin)
544 CALL mix_active_density_vector(active_space_env, p_old, p_solver, p_mixed)
548 p_active => active_space_env%p_active(ispin)
549 DO i1 = 1, nmo_active
550 m1 = active_space_env%active_orbitals(i1, ispin)
551 DO i2 = 1, nmo_active
553 m2 = active_space_env%active_orbitals(i2, ispin)
561 DEALLOCATE (p_solver)
static GRID_HOST_DEVICE int modulo(int a, int m)
Equivalent of Fortran's MODULO, which always return a positive number. https://gcc....
static GRID_HOST_DEVICE int idx(const orbital a)
Return coset index of given orbital angular momentum.
represent a full matrix distributed on many processors
subroutine, public cp_fm_get_element(matrix, irow_global, icol_global, alpha, local)
returns an element of a fm this value is valid on every cpu using this call is expensive
subroutine, public cp_fm_set_element(matrix, irow_global, icol_global, alpha)
sets an element of a matrix
Defines the basic variable types.
integer, parameter, public dp
Collection of simple mathematical functions and subroutines.
Dense density mixing for active-space embedding.
character(len=15) function, public active_space_mixing_label(active_space_env)
Return the current active-space mixer label for iteration output.
subroutine, public update_active_density(p_act_mo_a, active_space_env, p_act_mo_b)
Update active space density matrix from Fortran arrays.
subroutine, public initialize_active_space_mixing(active_space_env, as_input)
Initialize the density mixer used in the self-consistent active-space embedding loop.
The types needed for the calculation of active space Hamiltonians.
module that contains the definitions of the scf types
integer, parameter, public broyden_mixing_nr
integer, parameter, public modified_broyden_mixing_nr
integer, parameter, public no_mixing_nr
integer, parameter, public direct_mixing_nr
integer, parameter, public multisecant_mixing_nr
integer, parameter, public pulay_mixing_nr
subroutine, public mixing_storage_create(mixing_store, mixing_section, mixing_method, ecut)
creates a mixing_storage
integer, parameter, public gspace_mixing_nr