84 INTEGER,
PARAMETER :: k = 2, n = 3
86 COMPLEX(KIND=dp),
DIMENSION(n, k) :: direction, gradient, gradient_old, hc, q, x
87 COMPLEX(KIND=dp),
DIMENSION(n, n) :: hamiltonian
88 COMPLEX(KIND=dp),
DIMENSION(k, k) :: b, inverse_sqrt
89 INTEGER :: io_unit, mynode, nfail
90 INTEGER,
DIMENSION(:),
POINTER :: col_dist, col_k, row_dist, row_k, row_n
91 INTEGER,
DIMENSION(:, :),
POINTER :: pgrid
93 REAL(kind=
dp) :: error, fd_slope, hstep, old_error, slope
94 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: block_p
97 TYPE(
dbcsr_type),
TARGET :: b_im, b_re, f_im, f_re, g_im, g_re, &
98 hc_im, hc_re, q_im, q_re, sx_im, sx_re, &
106 CALL test_preconditioner_support(nfail)
107 NULLIFY (hc_im_p, hc_re_p, logger, para_env)
109 mynode = mp_comm%mepos
112 CALL test_antihermitian_spectral_norm(io_unit, nfail)
113 CALL test_fixed_n_mermin_energy(mynode, nfail)
114 CALL test_fixed_n_projector_frechet(mynode, nfail)
115 CALL test_finite_rotation_response(mynode, nfail)
116 CALL test_fixed_n_rotation_schur(mynode, nfail)
117 CALL test_fixed_n_multigroup_schur(mynode, nfail)
118 CALL test_roks_fixed_n_rotation_schur(mynode, nfail)
119 CALL test_symmetric_abs_solve(mynode, nfail)
120 CALL test_projected_response_update(mynode, nfail)
121 CALL test_symmetric_sr1_update(mynode, nfail)
122 CALL test_density_secant_hessian(mynode, nfail)
123 CALL test_joint_spin_density_secant(mynode, nfail)
124 CALL test_density_tangent(mynode, nfail)
125 CALL test_density_secant_moving_subspace(mynode, nfail)
127 CALL para_env%from_dup(mp_comm)
128 CALL cp_logger_create(logger, para_env=para_env, default_global_unit_nr=io_unit, &
129 close_global_unit_on_dealloc=.false.)
132 CALL dbcsr_init_lib(mp_comm%get_handle(), io_unit)
133 CALL test_real_rotation_frechet(para_env, nfail)
134 CALL test_complex_rotation_frechet(para_env, nfail)
135 CALL test_sparse_frechet_patterns(para_env, nfail)
136 CALL test_complex_ref_rotation(para_env, nfail)
138 CALL test_complex_preconditioner_gauge(para_env, nfail)
139 CALL test_complex_occupation_block_preconditioner(para_env, nfail)
140 CALL test_kpoint_ot_energy_weighted_density(para_env, io_unit, nfail)
142 x(:, 1) = [cmplx(1.10_dp, 0.10_dp, kind=
dp), cmplx(0.20_dp, -0.30_dp, kind=
dp), &
143 cmplx(-0.10_dp, 0.20_dp, kind=
dp)]
144 x(:, 2) = [cmplx(0.30_dp, 0.40_dp, kind=
dp), cmplx(0.90_dp, -0.20_dp, kind=
dp), &
145 cmplx(0.25_dp, 0.10_dp, kind=
dp)]
146 direction(:, 1) = [cmplx(0.17_dp, -0.09_dp, kind=
dp), cmplx(-0.21_dp, 0.13_dp, kind=
dp), &
147 cmplx(0.08_dp, 0.19_dp, kind=
dp)]
148 direction(:, 2) = [cmplx(-0.12_dp, 0.23_dp, kind=
dp), cmplx(0.16_dp, 0.07_dp, kind=
dp), &
149 cmplx(-0.14_dp, -0.11_dp, kind=
dp)]
151 hamiltonian(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
152 hamiltonian(1, 1) = cmplx(0.70_dp, 0.0_dp, kind=
dp)
153 hamiltonian(2, 2) = cmplx(-0.40_dp, 0.0_dp, kind=
dp)
154 hamiltonian(3, 3) = cmplx(1.10_dp, 0.0_dp, kind=
dp)
155 hamiltonian(1, 2) = cmplx(0.20_dp, 0.10_dp, kind=
dp)
156 hamiltonian(2, 1) = conjg(hamiltonian(1, 2))
157 hamiltonian(1, 3) = cmplx(-0.10_dp, 0.05_dp, kind=
dp)
158 hamiltonian(3, 1) = conjg(hamiltonian(1, 3))
159 hamiltonian(2, 3) = cmplx(0.15_dp, 0.20_dp, kind=
dp)
160 hamiltonian(3, 2) = conjg(hamiltonian(2, 3))
162 CALL dense_inverse_sqrt(matmul(conjg(transpose(x)), x), inverse_sqrt)
163 q = matmul(x, inverse_sqrt)
164 hc = 2.0_dp*matmul(hamiltonian, q)
166 ALLOCATE (pgrid(0:0, 0:0), row_dist(1), col_dist(1), row_n(1), row_k(1), col_k(1))
174 row_dist=row_dist, col_dist=col_dist)
176 row_dist=row_dist, col_dist=col_dist)
177 CALL test_complex_strict_derivative(dist_nk, dist_kk, row_n, row_k, col_k, para_env, nfail)
179 CALL create_one_block(x_re,
"complex_ref_x_re", dist_nk, row_n, col_k)
180 CALL create_one_block(x_im,
"complex_ref_x_im", dist_nk, row_n, col_k)
181 CALL create_one_block(sx_re,
"complex_ref_sx_re", dist_nk, row_n, col_k)
182 CALL create_one_block(sx_im,
"complex_ref_sx_im", dist_nk, row_n, col_k)
183 CALL create_one_block(hc_re,
"complex_ref_hc_re", dist_nk, row_n, col_k)
184 CALL create_one_block(hc_im,
"complex_ref_hc_im", dist_nk, row_n, col_k)
185 CALL create_one_block(g_re,
"complex_ref_g_re", dist_nk, row_n, col_k)
186 CALL create_one_block(g_im,
"complex_ref_g_im", dist_nk, row_n, col_k)
187 CALL create_one_block(q_re,
"complex_ref_q_re", dist_nk, row_n, col_k)
188 CALL create_one_block(q_im,
"complex_ref_q_im", dist_nk, row_n, col_k)
189 CALL create_one_block(f_re,
"complex_ref_f_re", dist_kk, row_k, col_k)
190 CALL create_one_block(f_im,
"complex_ref_f_im", dist_kk, row_k, col_k)
191 CALL create_one_block(b_re,
"complex_ref_b_re", dist_kk, row_k, col_k)
192 CALL create_one_block(b_im,
"complex_ref_b_im", dist_kk, row_k, col_k)
193 CALL create_one_block(tmp_kk,
"complex_ref_tmp_kk", dist_kk, row_k, col_k)
195 CALL put_complex_pair(x_re, x_im, x)
196 CALL put_complex_pair(sx_re, sx_im, x)
197 CALL put_complex_pair(hc_re, hc_im, hc)
198 CALL put_complex_pair(f_re, f_im, inverse_sqrt)
200 ot_env%has_complex_kpoint_state = .true.
201 ot_env%settings%eps_irac_filter_matrix = 0.0_dp
202 ot_env%matrix_x => x_re
203 ot_env%matrix_x_im => x_im
204 ot_env%matrix_sx => sx_re
205 ot_env%matrix_sx_im => sx_im
206 ot_env%matrix_gx => g_re
207 ot_env%matrix_gx_im => g_im
208 ot_env%matrix_ref_inv_sqrt => f_re
209 ot_env%matrix_ref_inv_sqrt_im => f_im
210 ot_env%buf1_k_k_sym => b_re
211 ot_env%buf2_k_k_sym => b_im
212 ot_env%buf3_k_k_sym => tmp_kk
213 ot_env%buf1_n_k => q_re
214 ot_env%buf1_n_k_dp => q_im
220 gradient(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
222 IF (found) gradient = gradient + cmplx(block_p, 0.0_dp, kind=
dp)
224 IF (found) gradient = gradient + cmplx(0.0_dp, block_p, kind=
dp)
227 fd_slope = (polar_energy(x + hstep*direction, hamiltonian) - &
228 polar_energy(x - hstep*direction, hamiltonian))/(2.0_dp*hstep)
229 slope = real(sum(conjg(gradient)*direction), kind=
dp)
230 error = abs(slope - fd_slope)
232 b = matmul(conjg(transpose(x)), hc)
233 gradient_old = hc - matmul(x, b)
234 old_error = abs(real(sum(conjg(gradient_old)*direction), kind=
dp) - fd_slope)
235 IF (error > 5.0e-8_dp .OR. old_error < 1.0e-3_dp) nfail = nfail + 1
237 IF (mynode == 0)
THEN
238 WRITE (io_unit,
'(A,3(1X,ES13.6))')
"complex finite-REF pullback: fd/predicted/error", &
239 fd_slope, slope, error
240 WRITE (io_unit,
'(A,1X,ES13.6)')
"discarded projected-gradient error", old_error
260 DEALLOCATE (pgrid, row_dist, col_dist, row_n, row_k, col_k)
262 CALL dbcsr_finalize_lib()
269 IF (nfail > 0) error stop
"qs_ot_complex_ref_unittest failed"
281 INTEGER,
INTENT(IN) :: io_unit
282 INTEGER,
INTENT(INOUT) :: nfail
284 INTEGER,
PARAMETER :: ndim = 3
286 COMPLEX(KIND=dp),
DIMENSION(ndim, ndim) :: a, actual, b, expected
288 REAL(KIND=
dp) :: error_cn, error_nc, error_nn
289 REAL(KIND=
dp),
DIMENSION(ndim, ndim) :: actual_im, actual_re
292 TYPE(
cp_fm_type) :: a_im, a_re, b_im, b_re, c_im, c_re
294 NULLIFY (blacs_env, matrix_struct)
297 a(i, j) = cmplx(0.13_dp*i - 0.07_dp*j, 0.05_dp*i*j - 0.11_dp*j, kind=
dp)
298 b(i, j) = cmplx(-0.09_dp*i + 0.17_dp*j, 0.08_dp*i*j + 0.04_dp*i, kind=
dp)
304 context=blacs_env, para_env=para_env)
317 a_re, a_im, b_re, b_im, 0.0_dp, c_re, c_im)
320 actual = cmplx(actual_re, actual_im, kind=
dp)
321 expected = matmul(a, b)
322 error_nn = maxval(abs(actual - expected))
325 a_re, a_im, b_re, b_im, 0.0_dp, c_re, c_im)
328 actual = cmplx(actual_re, actual_im, kind=
dp)
329 expected = matmul(conjg(transpose(a)), b)
330 error_cn = maxval(abs(actual - expected))
333 a_re, a_im, b_re, b_im, 0.0_dp, c_re, c_im)
336 actual = cmplx(actual_re, actual_im, kind=
dp)
337 expected = matmul(a, conjg(transpose(b)))
338 error_nc = maxval(abs(actual - expected))
340 IF (max(error_nn, error_cn, error_nc) > 1.0e-12_dp) nfail = nfail + 1
341 IF (io_unit >= 0)
WRITE (io_unit,
'(A,3(1X,ES13.6))') &
342 'split-complex GEMM N/N, C/N, N/C errors:', error_nn, error_cn, error_nc
361 SUBROUTINE test_kpoint_ot_energy_weighted_density(para_env, io_unit, nfail)
363 INTEGER,
INTENT(IN) :: io_unit
364 INTEGER,
INTENT(INOUT) :: nfail
366 INTEGER,
PARAMETER :: nao = 4, nmo = 3
368 COMPLEX(KIND=dp),
DIMENSION(nao, nao) :: actual, expected, hmat, rotated
369 COMPLEX(KIND=dp),
DIMENSION(nao, nmo) :: coeff, coeff_rot, hc_dense, hc_rot
370 COMPLEX(KIND=dp),
DIMENSION(nmo, nmo) :: hblock, lagrange, rotation
372 REAL(KIND=
dp) :: error, gauge_error, hermitian_error, &
374 REAL(KIND=
dp),
DIMENSION(nao, nao) :: actual_im, actual_re, rotated_im, &
376 REAL(KIND=
dp),
DIMENSION(nmo) :: occupation, uniform_occupation
379 TYPE(
cp_fm_type) :: coeff_im_fm, coeff_re_fm, hc_im_fm, &
380 hc_re_fm, wmat_im_fm, wmat_re_fm
382 NULLIFY (blacs_env, coeff_struct, hmat_struct)
384 hmat(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
385 hmat(1, 1) = cmplx(-0.8_dp, 0.0_dp, kind=
dp)
386 hmat(2, 2) = cmplx(0.1_dp, 0.0_dp, kind=
dp)
387 hmat(3, 3) = cmplx(0.7_dp, 0.0_dp, kind=
dp)
388 hmat(4, 4) = cmplx(1.4_dp, 0.0_dp, kind=
dp)
389 hmat(1, 2) = cmplx(0.21_dp, 0.13_dp, kind=
dp)
390 hmat(1, 3) = cmplx(-0.17_dp, 0.09_dp, kind=
dp)
391 hmat(1, 4) = cmplx(0.08_dp, -0.14_dp, kind=
dp)
392 hmat(2, 3) = cmplx(0.31_dp, -0.11_dp, kind=
dp)
393 hmat(2, 4) = cmplx(-0.19_dp, -0.07_dp, kind=
dp)
394 hmat(3, 4) = cmplx(0.27_dp, 0.16_dp, kind=
dp)
397 hmat(j, i) = conjg(hmat(i, j))
402 phase = 2.0_dp*pi*real((i - 1)*(j - 1), kind=
dp)/real(nao, kind=
dp)
403 coeff(i, j) = cmplx(cos(phase), sin(phase), kind=
dp)/sqrt(real(nao, kind=
dp))
406 hc_dense = matmul(hmat, coeff)
407 occupation = [1.0_dp, 0.63_dp, 0.11_dp]
409 hblock = matmul(conjg(transpose(coeff)), hc_dense)
411 lagrange(:, j) = hblock(:, j)*occupation(j)
413 lagrange = 0.5_dp*(lagrange + conjg(transpose(lagrange)))
414 expected = matmul(matmul(coeff, lagrange), conjg(transpose(coeff)))
418 context=blacs_env, para_env=para_env)
420 context=blacs_env, para_env=para_env)
433 coeff_re_fm, coeff_im_fm, hc_re_fm, hc_im_fm, occupation, &
434 wmat_re_fm, wmat_im_fm)
437 actual = cmplx(actual_re, actual_im, kind=
dp)
438 error = maxval(abs(actual - expected))
439 hermitian_error = maxval(abs(actual - conjg(transpose(actual))))
441 rotation(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
442 rotation(1, 1) = cmplx(sqrt(0.5_dp), 0.0_dp, kind=
dp)
443 rotation(1, 2) = cmplx(0.0_dp, sqrt(0.5_dp), kind=
dp)
444 rotation(2, 1) = cmplx(0.0_dp, sqrt(0.5_dp), kind=
dp)
445 rotation(2, 2) = cmplx(sqrt(0.5_dp), 0.0_dp, kind=
dp)
446 rotation(3, 3) = cmplx(0.0_dp, 1.0_dp, kind=
dp)
447 coeff_rot = matmul(coeff, rotation)
448 hc_rot = matmul(hc_dense, rotation)
449 uniform_occupation(:) = 1.0_dp
455 coeff_re_fm, coeff_im_fm, hc_re_fm, hc_im_fm, uniform_occupation, &
456 wmat_re_fm, wmat_im_fm)
459 rotated = cmplx(rotated_re, rotated_im, kind=
dp)
460 expected = matmul(matmul(coeff, hblock), conjg(transpose(coeff)))
461 gauge_error = maxval(abs(rotated - expected))
463 IF (error > 5.0e-12_dp .OR. hermitian_error > 5.0e-12_dp .OR. &
464 gauge_error > 5.0e-12_dp) nfail = nfail + 1
465 IF (io_unit >= 0)
THEN
466 WRITE (io_unit,
'(A,3(1X,ES13.6))')
'complex OT W error/hermitian/gauge', &
467 error, hermitian_error, gauge_error
480 END SUBROUTINE test_kpoint_ot_energy_weighted_density
486 SUBROUTINE test_antihermitian_spectral_norm(io_unit, nfail)
487 INTEGER,
INTENT(IN) :: io_unit
488 INTEGER,
INTENT(INOUT) :: nfail
490 COMPLEX(KIND=dp),
DIMENSION(3) :: phase
491 COMPLEX(KIND=dp),
DIMENSION(3, 3) :: generator, transformed
493 REAL(KIND=
dp) :: error, norm, transformed_norm
495 generator(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
496 generator(1, 2) = cmplx(0.3_dp, 0.4_dp, kind=
dp)
497 generator(2, 1) = -conjg(generator(1, 2))
498 phase = exp(cmplx(0.0_dp, 1.0_dp, kind=
dp)*[0.37_dp, -0.51_dp, 0.83_dp])
501 transformed(i, j) = conjg(phase(i))*generator(i, j)*phase(j)
507 error = max(abs(norm - 0.5_dp), abs(transformed_norm - norm))
508 IF (io_unit >= 0)
WRITE (io_unit,
'(A,ES14.6)') &
509 "complex rotation spectral-norm error: ", error
510 IF (error > 1.0e-13_dp) nfail = nfail + 1
512 END SUBROUTINE test_antihermitian_spectral_norm
519 SUBROUTINE test_fixed_n_mermin_energy(mynode, nfail)
520 INTEGER,
INTENT(IN) :: mynode
521 INTEGER,
INTENT(INOUT) :: nfail
523 INTEGER,
PARAMETER :: nbands = 4
524 REAL(KIND=
dp),
PARAMETER :: fd_step = 1.0e-6_dp, maxocc = 2.0_dp, &
525 target_electrons = 2.25_dp, &
526 temperature = 0.07_dp
528 REAL(KIND=
dp) :: fd_slope, gradient_error, hessian_error, &
529 mu, predicted_slope, response_sum, &
531 REAL(KIND=
dp),
DIMENSION(nbands) :: direction, energies, gradient, gradient_minus, &
532 gradient_plus, hessian_action, occupation, rayleigh, response, response_minus, &
533 response_plus, weights
534 REAL(KIND=
dp),
DIMENSION(nbands, nbands) :: hessian
536 energies(:) = [-0.24_dp, -0.05_dp, 0.08_dp, 0.31_dp]
537 rayleigh(:) = [-0.19_dp, -0.02_dp, 0.04_dp, 0.27_dp]
538 weights(:) = [0.35_dp, 0.35_dp, 0.65_dp, 0.65_dp]
539 direction(:) = [0.17_dp, -0.11_dp, 0.08_dp, -0.05_dp]
541 CALL fixed_n_fermi_occupations(energies, weights, target_electrons, temperature, &
542 maxocc, occupation, mu)
543 response(:) = weights(:)*occupation(:)*(maxocc - occupation(:))/(maxocc*temperature)
544 response_sum = sum(response)
545 weighted_residual = dot_product(response, rayleigh - energies)
547 weighted_residual, gradient)
549 fd_slope = (fixed_n_mermin_value(rayleigh, energies + fd_step*direction, weights, &
550 target_electrons, temperature, maxocc) - &
551 fixed_n_mermin_value(rayleigh, energies - fd_step*direction, weights, &
552 target_electrons, temperature, maxocc))/(2.0_dp*fd_step)
553 predicted_slope = dot_product(gradient, direction)
554 gradient_error = max(abs(fd_slope - predicted_slope), abs(sum(gradient)))
557 rayleigh(:) = energies(:)
559 hessian_action(:) = matmul(hessian, direction)
561 CALL fixed_n_fermi_occupations(energies + fd_step*direction, weights, target_electrons, &
562 temperature, maxocc, occupation, mu)
563 response_plus(:) = weights(:)*occupation(:)*(maxocc - occupation(:))/(maxocc*temperature)
564 weighted_residual = dot_product(response_plus, rayleigh - energies - fd_step*direction)
566 sum(response_plus), weighted_residual, gradient_plus)
568 CALL fixed_n_fermi_occupations(energies - fd_step*direction, weights, target_electrons, &
569 temperature, maxocc, occupation, mu)
570 response_minus(:) = weights(:)*occupation(:)*(maxocc - occupation(:))/(maxocc*temperature)
571 weighted_residual = dot_product(response_minus, rayleigh - energies + fd_step*direction)
573 sum(response_minus), weighted_residual, gradient_minus)
575 hessian_error = maxval(abs((gradient_plus - gradient_minus)/(2.0_dp*fd_step) - &
577 hessian_error = max(hessian_error, maxval(abs(hessian - transpose(hessian))))
578 hessian_error = max(hessian_error, maxval(abs(matmul(hessian, spread(1.0_dp, 1, nbands)))))
580 IF (gradient_error > 2.0e-8_dp .OR. hessian_error > 2.0e-7_dp) nfail = nfail + 1
581 IF (mynode == 0)
THEN
582 WRITE (io_unit,
'(A,2(1X,ES13.6))')
"fixed-N Mermin gradient/Hessian errors:", &
583 gradient_error, hessian_error
586 END SUBROUTINE test_fixed_n_mermin_energy
593 SUBROUTINE test_fixed_n_projector_frechet(mynode, nfail)
594 INTEGER,
INTENT(IN) :: mynode
595 INTEGER,
INTENT(INOUT) :: nfail
597 INTEGER,
PARAMETER :: nbands = 3
598 REAL(KIND=
dp),
PARAMETER :: fd_step = 1.0e-6_dp, kpoint_weight = 0.75_dp, maxocc = 2.0_dp, &
599 target_electrons = 2.10_dp, temperature = 0.09_dp
601 COMPLEX(KIND=dp),
DIMENSION(nbands, nbands) :: dchc, derivative, derivative_fd, &
602 hamiltonian, projector_minus, &
603 projector_plus, vectors
605 REAL(KIND=
dp) :: error, mu, trace_error
606 REAL(KIND=
dp),
DIMENSION(nbands) :: eigenvalues, occupation, response, &
609 hamiltonian(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
610 hamiltonian(1, 1) = cmplx(-0.22_dp, 0.0_dp, kind=
dp)
611 hamiltonian(2, 2) = cmplx(0.03_dp, 0.0_dp, kind=
dp)
612 hamiltonian(3, 3) = cmplx(0.28_dp, 0.0_dp, kind=
dp)
613 hamiltonian(1, 2) = cmplx(0.04_dp, -0.03_dp, kind=
dp)
614 hamiltonian(2, 1) = conjg(hamiltonian(1, 2))
615 hamiltonian(2, 3) = cmplx(-0.02_dp, 0.05_dp, kind=
dp)
616 hamiltonian(3, 2) = conjg(hamiltonian(2, 3))
618 dchc(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
619 dchc(1, 1) = cmplx(0.13_dp, 0.0_dp, kind=
dp)
620 dchc(2, 2) = cmplx(-0.08_dp, 0.0_dp, kind=
dp)
621 dchc(3, 3) = cmplx(0.05_dp, 0.0_dp, kind=
dp)
622 dchc(1, 2) = cmplx(0.17_dp, -0.11_dp, kind=
dp)
623 dchc(2, 1) = conjg(dchc(1, 2))
624 dchc(2, 3) = cmplx(0.12_dp, 0.09_dp, kind=
dp)
625 dchc(3, 2) = conjg(dchc(2, 3))
628 weights(:) = kpoint_weight
629 CALL fixed_n_fermi_occupations(eigenvalues, weights, target_electrons, temperature, &
630 maxocc, occupation, mu)
631 response(:) = weights(:)*occupation(:)*(maxocc - occupation(:))/(maxocc*temperature)
633 response, sum(response), derivative)
635 CALL fixed_n_spectral_projector(hamiltonian + fd_step*dchc, weights, target_electrons, &
636 temperature, maxocc, projector_plus)
637 CALL fixed_n_spectral_projector(hamiltonian - fd_step*dchc, weights, target_electrons, &
638 temperature, maxocc, projector_minus)
639 derivative_fd(:, :) = (projector_plus - projector_minus)/(2.0_dp*fd_step)
640 error = maxval(abs(derivative - derivative_fd))
643 trace_error = trace_error + real(derivative(i, i), kind=
dp)
645 error = max(error, abs(trace_error))
647 IF (error > 3.0e-7_dp) nfail = nfail + 1
648 IF (mynode == 0)
WRITE (io_unit,
'(A,1X,ES13.6)') &
649 "fixed-N complex occupation-projector error:", error
651 END SUBROUTINE test_fixed_n_projector_frechet
658 SUBROUTINE test_finite_rotation_response(mynode, nfail)
659 INTEGER,
INTENT(IN) :: mynode
660 INTEGER,
INTENT(INOUT) :: nfail
662 INTEGER,
PARAMETER :: nbands = 3, nrotation = 6
663 REAL(KIND=
dp),
PARAMETER :: fd_step = 2.0e-4_dp, &
664 kpoint_weight = 0.625_dp
666 COMPLEX(KIND=dp),
DIMENSION(nbands, nbands) :: base_hamiltonian, chc, &
667 direction_generator, generator, &
668 rotation, rotation_minus, rotation_plus
670 REAL(KIND=
dp) :: energy, energy_minus, energy_plus, &
671 gradient_error, hessian_error, &
672 rayleigh_error, symmetry_error
673 REAL(KIND=
dp),
DIMENSION(nbands) :: occupation, rayleigh_minus, rayleigh_plus
674 REAL(KIND=
dp),
DIMENSION(nbands, nrotation) :: rayleigh_response
675 REAL(KIND=
dp),
DIMENSION(nrotation) :: direction, gradient
676 REAL(KIND=
dp),
DIMENSION(nrotation, nrotation) :: hessian
678 base_hamiltonian(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
679 base_hamiltonian(1, 1) = cmplx(-0.31_dp, 0.0_dp, kind=
dp)
680 base_hamiltonian(2, 2) = cmplx(0.07_dp, 0.0_dp, kind=
dp)
681 base_hamiltonian(3, 3) = cmplx(0.42_dp, 0.0_dp, kind=
dp)
682 base_hamiltonian(1, 2) = cmplx(0.09_dp, -0.06_dp, kind=
dp)
683 base_hamiltonian(1, 3) = cmplx(-0.04_dp, 0.08_dp, kind=
dp)
684 base_hamiltonian(2, 3) = cmplx(0.11_dp, 0.05_dp, kind=
dp)
686 base_hamiltonian(i, 1:i - 1) = conjg(base_hamiltonian(1:i - 1, i))
689 generator(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
690 generator(1, 2) = cmplx(0.17_dp, -0.08_dp, kind=
dp)
691 generator(1, 3) = cmplx(-0.09_dp, 0.04_dp, kind=
dp)
692 generator(2, 3) = cmplx(0.12_dp, 0.07_dp, kind=
dp)
694 generator(i, 1:i - 1) = -conjg(generator(1:i - 1, i))
697 direction(:) = [0.14_dp, -0.07_dp, -0.11_dp, 0.09_dp, 0.05_dp, 0.13_dp]
698 direction_generator(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
699 direction_generator(1, 2) = cmplx(direction(1), direction(2), kind=
dp)
700 direction_generator(2, 1) = -conjg(direction_generator(1, 2))
701 direction_generator(1, 3) = cmplx(direction(3), direction(4), kind=
dp)
702 direction_generator(3, 1) = -conjg(direction_generator(1, 3))
703 direction_generator(2, 3) = cmplx(direction(5), direction(6), kind=
dp)
704 direction_generator(3, 2) = -conjg(direction_generator(2, 3))
705 occupation(:) = [1.73_dp, 0.88_dp, 0.19_dp]
707 rotation(:, :) = dense_antihermitian_exp(generator)
708 chc(:, :) = matmul(conjg(transpose(rotation)), &
709 matmul(base_hamiltonian, rotation))
711 gradient, hessian, rayleigh_response)
713 rotation_plus(:, :) = dense_antihermitian_exp(generator + fd_step*direction_generator)
714 rotation_minus(:, :) = dense_antihermitian_exp(generator - fd_step*direction_generator)
715 energy = finite_rotation_energy(rotation, base_hamiltonian, occupation, kpoint_weight)
716 energy_plus = finite_rotation_energy(rotation_plus, base_hamiltonian, occupation, kpoint_weight)
717 energy_minus = finite_rotation_energy(rotation_minus, base_hamiltonian, occupation, kpoint_weight)
718 gradient_error = abs((energy_plus - energy_minus)/(2.0_dp*fd_step) - &
719 dot_product(gradient, direction))
720 hessian_error = abs((energy_plus - 2.0_dp*energy + energy_minus)/fd_step**2 - &
721 dot_product(direction, matmul(hessian, direction)))
722 symmetry_error = maxval(abs(hessian - transpose(hessian)))
725 rayleigh_plus(i) = real(dot_product(rotation_plus(:, i), &
726 matmul(base_hamiltonian, rotation_plus(:, i))), kind=
dp)
727 rayleigh_minus(i) = real(dot_product(rotation_minus(:, i), &
728 matmul(base_hamiltonian, rotation_minus(:, i))), kind=
dp)
730 rayleigh_error = maxval(abs((rayleigh_plus - rayleigh_minus)/(2.0_dp*fd_step) - &
731 matmul(rayleigh_response, direction)))
733 IF (gradient_error > 5.0e-8_dp .OR. hessian_error > 2.0e-6_dp .OR. &
734 rayleigh_error > 2.0e-7_dp .OR. symmetry_error > 1.0e-12_dp) nfail = nfail + 1
735 IF (mynode == 0)
THEN
736 WRITE (io_unit,
'(A,4(1X,ES13.6))')
"finite complex rotation response errors:", &
737 gradient_error, hessian_error, rayleigh_error, symmetry_error
740 END SUBROUTINE test_finite_rotation_response
747 SUBROUTINE test_fixed_n_rotation_schur(mynode, nfail)
748 INTEGER,
INTENT(IN) :: mynode
749 INTEGER,
INTENT(INOUT) :: nfail
751 INTEGER,
PARAMETER :: nbands = 3, nrotation = 6
752 REAL(KIND=
dp),
PARAMETER :: fd_step = 1.0e-4_dp, &
753 kpoint_weight = 0.625_dp, &
754 maxocc = 2.0_dp, temperature = 0.08_dp
756 COMPLEX(KIND=dp),
DIMENSION(nbands, nbands) :: base_hamiltonian, chc, &
757 direction_generator, generator, &
758 rotation, rotation_minus, rotation_plus
760 REAL(KIND=
dp) :: curvature, curvature_error, &
761 energy_minus, energy_plus, &
762 energy_zero, mu, response_sum, &
764 REAL(KIND=
dp),
DIMENSION(nbands) :: energy_coordinate, energy_direction, energy_gradient, &
765 energy_minus_coordinate, energy_plus_coordinate, occupation, rayleigh, rayleigh_minus, &
766 rayleigh_plus, response, weights
767 REAL(KIND=
dp),
DIMENSION(nbands, nbands) :: energy_hessian
768 REAL(KIND=
dp),
DIMENSION(nbands, nrotation) :: rayleigh_response
769 REAL(KIND=
dp),
DIMENSION(nrotation) :: coupling, rotation_direction, &
770 rotation_gradient, schur_rhs
771 REAL(KIND=
dp),
DIMENSION(nrotation, nrotation) :: rotation_hessian, schur, schur_block
773 base_hamiltonian(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
774 base_hamiltonian(1, 1) = cmplx(-0.31_dp, 0.0_dp, kind=
dp)
775 base_hamiltonian(2, 2) = cmplx(0.07_dp, 0.0_dp, kind=
dp)
776 base_hamiltonian(3, 3) = cmplx(0.42_dp, 0.0_dp, kind=
dp)
777 base_hamiltonian(1, 2) = cmplx(0.09_dp, -0.06_dp, kind=
dp)
778 base_hamiltonian(1, 3) = cmplx(-0.04_dp, 0.08_dp, kind=
dp)
779 base_hamiltonian(2, 3) = cmplx(0.11_dp, 0.05_dp, kind=
dp)
781 base_hamiltonian(i, 1:i - 1) = conjg(base_hamiltonian(1:i - 1, i))
784 generator(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
785 generator(1, 2) = cmplx(0.17_dp, -0.08_dp, kind=
dp)
786 generator(1, 3) = cmplx(-0.09_dp, 0.04_dp, kind=
dp)
787 generator(2, 3) = cmplx(0.12_dp, 0.07_dp, kind=
dp)
789 generator(i, 1:i - 1) = -conjg(generator(1:i - 1, i))
791 rotation_direction(:) = [0.14_dp, -0.07_dp, -0.11_dp, 0.09_dp, 0.05_dp, 0.13_dp]
792 energy_direction(:) = [0.08_dp, -0.11_dp, 0.03_dp]
793 direction_generator(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
794 direction_generator(1, 2) = cmplx(rotation_direction(1), rotation_direction(2), kind=
dp)
795 direction_generator(2, 1) = -conjg(direction_generator(1, 2))
796 direction_generator(1, 3) = cmplx(rotation_direction(3), rotation_direction(4), kind=
dp)
797 direction_generator(3, 1) = -conjg(direction_generator(1, 3))
798 direction_generator(2, 3) = cmplx(rotation_direction(5), rotation_direction(6), kind=
dp)
799 direction_generator(3, 2) = -conjg(direction_generator(2, 3))
801 rotation(:, :) = dense_antihermitian_exp(generator)
802 chc(:, :) = matmul(conjg(transpose(rotation)), matmul(base_hamiltonian, rotation))
804 rayleigh(i) = real(chc(i, i), kind=
dp)
806 energy_coordinate(:) = rayleigh(:)
807 weights(:) = kpoint_weight
808 CALL fixed_n_fermi_occupations(energy_coordinate, weights, 1.7_dp, temperature, &
809 maxocc, occupation, mu)
810 response(:) = weights*occupation*(maxocc - occupation)/(maxocc*temperature)
811 response_sum = sum(response)
813 rotation_gradient, rotation_hessian, rayleigh_response)
815 0.0_dp, energy_gradient)
818 rotation_hessian, rayleigh_response, response, rotation_gradient, energy_gradient, &
819 schur_block, coupling, schur_rhs)
820 schur(:, :) = schur_block + spread(coupling, dim=2, ncopies=nrotation)* &
821 spread(coupling, dim=1, ncopies=nrotation)/response_sum
822 schur_error = maxval(abs(schur - rotation_hessian + &
823 matmul(transpose(rayleigh_response), &
824 matmul(energy_hessian, rayleigh_response))))
826 rotation_plus(:, :) = dense_antihermitian_exp(generator + fd_step*direction_generator)
827 rotation_minus(:, :) = dense_antihermitian_exp(generator - fd_step*direction_generator)
829 rayleigh_plus(i) = real(dot_product(rotation_plus(:, i), &
830 matmul(base_hamiltonian, rotation_plus(:, i))), kind=
dp)
831 rayleigh_minus(i) = real(dot_product(rotation_minus(:, i), &
832 matmul(base_hamiltonian, rotation_minus(:, i))), kind=
dp)
834 energy_plus_coordinate(:) = energy_coordinate + fd_step*energy_direction
835 energy_minus_coordinate(:) = energy_coordinate - fd_step*energy_direction
836 energy_zero = fixed_n_mermin_value(rayleigh, energy_coordinate, weights, 1.7_dp, &
838 energy_plus = fixed_n_mermin_value(rayleigh_plus, energy_plus_coordinate, weights, 1.7_dp, &
840 energy_minus = fixed_n_mermin_value(rayleigh_minus, energy_minus_coordinate, weights, 1.7_dp, &
842 curvature = dot_product(rotation_direction, matmul(rotation_hessian, rotation_direction)) - &
843 2.0_dp*dot_product(energy_direction, &
844 matmul(energy_hessian, &
845 matmul(rayleigh_response, rotation_direction))) + &
846 dot_product(energy_direction, matmul(energy_hessian, energy_direction))
847 curvature_error = abs((energy_plus - 2.0_dp*energy_zero + energy_minus)/fd_step**2 - curvature)
849 IF (schur_error > 2.0e-11_dp .OR. curvature_error > 3.0e-6_dp) nfail = nfail + 1
850 IF (mynode == 0)
THEN
851 WRITE (io_unit,
'(A,2(1X,ES13.6))')
"fixed-N rotation Schur errors:", &
852 schur_error, curvature_error
855 END SUBROUTINE test_fixed_n_rotation_schur
862 SUBROUTINE test_fixed_n_multigroup_schur(mynode, nfail)
863 INTEGER,
INTENT(IN) :: mynode
864 INTEGER,
INTENT(INOUT) :: nfail
866 INTEGER,
PARAMETER :: nenergy = 4, ngroups = 2, nrotation = 3
868 INTEGER,
DIMENSION(nenergy) :: response_group
869 REAL(KIND=
dp) :: coupling_error, rhs_error, schur_error
870 REAL(KIND=
dp),
DIMENSION(nenergy) :: energy_gradient, response_weight
871 REAL(KIND=
dp),
DIMENSION(nenergy, nrotation) :: rayleigh_response
872 REAL(KIND=
dp),
DIMENSION(nrotation) :: rotation_gradient, schur_rhs
873 REAL(KIND=
dp),
DIMENSION(nrotation, ngroups) :: coupling
874 REAL(KIND=
dp),
DIMENSION(nrotation, nrotation) :: expected, rotation_hessian, schur_block
876 rotation_hessian(:, :) = reshape( &
877 [2.3_dp, 0.2_dp, -0.1_dp, 0.2_dp, 1.8_dp, 0.3_dp, -0.1_dp, 0.3_dp, 1.5_dp], &
878 [nrotation, nrotation])
879 rayleigh_response(:, :) = reshape( &
880 [0.4_dp, -0.2_dp, 0.1_dp, 0.3_dp, &
881 -0.1_dp, 0.5_dp, 0.2_dp, -0.4_dp, &
882 0.3_dp, 0.1_dp, -0.5_dp, 0.2_dp], &
883 [nenergy, nrotation])
884 response_weight(:) = [0.7_dp, 0.5_dp, 0.4_dp, 0.2_dp]
885 response_group(:) = [1, 1, 2, 2]
886 rotation_gradient(:) = [0.2_dp, -0.1_dp, 0.3_dp]
887 energy_gradient(:) = [0.04_dp, -0.03_dp, 0.02_dp, -0.01_dp]
890 rotation_hessian, rayleigh_response, response_weight, response_group, &
891 rotation_gradient, energy_gradient, schur_block, coupling, schur_rhs)
893 expected(:, :) = rotation_hessian - &
894 matmul(transpose(rayleigh_response), &
896 [0.2916666666666667_dp, -0.2916666666666667_dp, 0.0_dp, 0.0_dp, &
897 -0.2916666666666667_dp, 0.2916666666666667_dp, 0.0_dp, 0.0_dp, &
898 0.0_dp, 0.0_dp, 0.1333333333333333_dp, -0.1333333333333333_dp, &
899 0.0_dp, 0.0_dp, -0.1333333333333333_dp, 0.1333333333333333_dp], &
900 [nenergy, nenergy]), rayleigh_response))
901 schur_error = maxval(abs( &
903 matmul(coupling(:, 1:1), transpose(coupling(:, 1:1)))/1.2_dp + &
904 matmul(coupling(:, 2:2), transpose(coupling(:, 2:2)))/0.6_dp - expected))
905 coupling_error = maxval(abs(coupling(:, 1) - &
906 matmul(transpose(rayleigh_response(1:2, :)), &
907 response_weight(1:2))))
908 coupling_error = max(coupling_error, maxval(abs(coupling(:, 2) - &
909 matmul(transpose(rayleigh_response(3:4, :)), &
910 response_weight(3:4)))))
911 rhs_error = maxval(abs(schur_rhs - rotation_gradient - &
912 matmul(transpose(rayleigh_response), energy_gradient)))
914 IF (max(schur_error, coupling_error, rhs_error) > 2.0e-14_dp) nfail = nfail + 1
915 IF (mynode == 0)
THEN
916 WRITE (io_unit,
'(A,3(1X,ES13.6))')
"fixed-N multigroup Schur errors:", &
917 schur_error, coupling_error, rhs_error
920 END SUBROUTINE test_fixed_n_multigroup_schur
927 SUBROUTINE test_roks_fixed_n_rotation_schur(mynode, nfail)
928 INTEGER,
INTENT(IN) :: mynode
929 INTEGER,
INTENT(INOUT) :: nfail
931 INTEGER,
PARAMETER :: nbands = 3, nenergy = 6, ngroups = 2, &
933 REAL(KIND=
dp),
PARAMETER :: fd_step = 1.0e-4_dp, &
934 kpoint_weight = 0.7_dp, &
935 maxocc = 1.0_dp, temperature = 0.09_dp
937 COMPLEX(KIND=dp),
DIMENSION(nbands, nbands) :: chc_a, chc_b, direction_generator, generator, &
938 hamiltonian_a, hamiltonian_b, rotation, rotation_minus, rotation_plus
940 INTEGER,
DIMENSION(nenergy) :: response_group
941 REAL(KIND=
dp) :: curvature, curvature_a, curvature_b, curvature_error, energy_minus, &
942 energy_minus_a, energy_minus_b, energy_plus, energy_plus_a, energy_plus_b, energy_zero, &
943 energy_zero_a, energy_zero_b, mu_a, mu_b, response_sum_a, response_sum_b, schur_error
944 REAL(KIND=
dp),
DIMENSION(nbands) :: energy_a, energy_a_minus, energy_a_plus, energy_b, &
945 energy_b_minus, energy_b_plus, occupation_a, occupation_b, rayleigh_a, rayleigh_a_minus, &
946 rayleigh_a_plus, rayleigh_b, rayleigh_b_minus, rayleigh_b_plus, response_a, response_b, &
948 REAL(KIND=
dp),
DIMENSION(nbands, nrotation) :: spin_rayleigh_response
949 REAL(KIND=
dp),
DIMENSION(nenergy) :: energy_direction, energy_gradient, &
951 REAL(KIND=
dp),
DIMENSION(nenergy, nenergy) :: energy_hessian
952 REAL(KIND=
dp),
DIMENSION(nenergy, nrotation) :: rayleigh_response
953 REAL(KIND=
dp),
DIMENSION(nrotation) :: rotation_direction, rotation_gradient, &
954 schur_rhs, spin_gradient
955 REAL(KIND=
dp),
DIMENSION(nrotation, ngroups) :: coupling
956 REAL(KIND=
dp),
DIMENSION(nrotation, nrotation) :: rotation_hessian, rotation_hessian_a, &
957 rotation_hessian_b, schur, &
958 schur_block, spin_hessian
960 hamiltonian_a(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
961 hamiltonian_b(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
962 hamiltonian_a(1, 1) = -0.42_dp
963 hamiltonian_a(2, 2) = 0.03_dp
964 hamiltonian_a(3, 3) = 0.37_dp
965 hamiltonian_a(1, 2) = cmplx(0.08_dp, -0.05_dp, kind=
dp)
966 hamiltonian_a(1, 3) = cmplx(-0.03_dp, 0.07_dp, kind=
dp)
967 hamiltonian_a(2, 3) = cmplx(0.09_dp, 0.04_dp, kind=
dp)
968 hamiltonian_b(1, 1) = -0.31_dp
969 hamiltonian_b(2, 2) = 0.11_dp
970 hamiltonian_b(3, 3) = 0.46_dp
971 hamiltonian_b(1, 2) = cmplx(-0.06_dp, 0.02_dp, kind=
dp)
972 hamiltonian_b(1, 3) = cmplx(0.05_dp, 0.04_dp, kind=
dp)
973 hamiltonian_b(2, 3) = cmplx(-0.07_dp, 0.06_dp, kind=
dp)
975 hamiltonian_a(i, 1:i - 1) = conjg(hamiltonian_a(1:i - 1, i))
976 hamiltonian_b(i, 1:i - 1) = conjg(hamiltonian_b(1:i - 1, i))
979 generator(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
980 generator(1, 2) = cmplx(0.14_dp, -0.06_dp, kind=
dp)
981 generator(1, 3) = cmplx(-0.08_dp, 0.05_dp, kind=
dp)
982 generator(2, 3) = cmplx(0.10_dp, 0.03_dp, kind=
dp)
984 generator(i, 1:i - 1) = -conjg(generator(1:i - 1, i))
986 rotation_direction(:) = [0.09_dp, -0.04_dp, -0.07_dp, 0.06_dp, 0.03_dp, 0.08_dp]
987 energy_direction(:) = [0.05_dp, -0.04_dp, 0.02_dp, -0.03_dp, 0.06_dp, -0.01_dp]
988 direction_generator(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
989 direction_generator(1, 2) = cmplx(rotation_direction(1), rotation_direction(2), kind=
dp)
990 direction_generator(2, 1) = -conjg(direction_generator(1, 2))
991 direction_generator(1, 3) = cmplx(rotation_direction(3), rotation_direction(4), kind=
dp)
992 direction_generator(3, 1) = -conjg(direction_generator(1, 3))
993 direction_generator(2, 3) = cmplx(rotation_direction(5), rotation_direction(6), kind=
dp)
994 direction_generator(3, 2) = -conjg(direction_generator(2, 3))
996 rotation(:, :) = dense_antihermitian_exp(generator)
997 chc_a(:, :) = matmul(conjg(transpose(rotation)), matmul(hamiltonian_a, rotation))
998 chc_b(:, :) = matmul(conjg(transpose(rotation)), matmul(hamiltonian_b, rotation))
1000 rayleigh_a(i) = real(chc_a(i, i), kind=
dp)
1001 rayleigh_b(i) = real(chc_b(i, i), kind=
dp)
1003 energy_a(:) = rayleigh_a
1004 energy_b(:) = rayleigh_b
1005 weights(:) = kpoint_weight
1006 CALL fixed_n_fermi_occupations(energy_a, weights, 1.65_dp, temperature, &
1007 maxocc, occupation_a, mu_a)
1008 CALL fixed_n_fermi_occupations(energy_b, weights, 0.95_dp, temperature, &
1009 maxocc, occupation_b, mu_b)
1010 response_a(:) = weights*occupation_a*(maxocc - occupation_a)/(maxocc*temperature)
1011 response_b(:) = weights*occupation_b*(maxocc - occupation_b)/(maxocc*temperature)
1012 response_sum_a = sum(response_a)
1013 response_sum_b = sum(response_b)
1014 response(1:nbands) = response_a
1015 response(nbands + 1:nenergy) = response_b
1016 response_group(:) = [1, 1, 1, 2, 2, 2]
1019 chc_a, generator, occupation_a, kpoint_weight, spin_gradient, spin_hessian, &
1020 spin_rayleigh_response)
1021 rotation_gradient(:) = spin_gradient
1022 rotation_hessian_a(:, :) = spin_hessian
1023 rayleigh_response(1:nbands, :) = spin_rayleigh_response
1025 chc_b, generator, occupation_b, kpoint_weight, spin_gradient, spin_hessian, &
1026 spin_rayleigh_response)
1027 rotation_gradient(:) = rotation_gradient + spin_gradient
1028 rotation_hessian_b(:, :) = spin_hessian
1029 rotation_hessian(:, :) = rotation_hessian_a + rotation_hessian_b
1030 rayleigh_response(nbands + 1:nenergy, :) = spin_rayleigh_response
1033 rayleigh_a, energy_a, response_a, response_sum_a, 0.0_dp, &
1034 energy_gradient(1:nbands))
1036 rayleigh_b, energy_b, response_b, response_sum_b, 0.0_dp, &
1037 energy_gradient(nbands + 1:nenergy))
1038 energy_hessian(:, :) = 0.0_dp
1040 response_a, response_sum_a, energy_hessian(1:nbands, 1:nbands))
1042 response_b, response_sum_b, energy_hessian(nbands + 1:nenergy, nbands + 1:nenergy))
1044 rotation_hessian, rayleigh_response, response, response_group, rotation_gradient, &
1045 energy_gradient, schur_block, coupling, schur_rhs)
1046 schur(:, :) = schur_block + &
1047 matmul(coupling(:, 1:1), transpose(coupling(:, 1:1)))/response_sum_a + &
1048 matmul(coupling(:, 2:2), transpose(coupling(:, 2:2)))/response_sum_b
1049 schur_error = maxval(abs(schur - rotation_hessian + &
1050 matmul(transpose(rayleigh_response), &
1051 matmul(energy_hessian, rayleigh_response))))
1053 rotation_plus(:, :) = dense_antihermitian_exp(generator + fd_step*direction_generator)
1054 rotation_minus(:, :) = dense_antihermitian_exp(generator - fd_step*direction_generator)
1056 rayleigh_a_plus(i) = real(dot_product(rotation_plus(:, i), &
1057 matmul(hamiltonian_a, rotation_plus(:, i))), kind=
dp)
1058 rayleigh_a_minus(i) = real(dot_product(rotation_minus(:, i), &
1059 matmul(hamiltonian_a, rotation_minus(:, i))), kind=
dp)
1060 rayleigh_b_plus(i) = real(dot_product(rotation_plus(:, i), &
1061 matmul(hamiltonian_b, rotation_plus(:, i))), kind=
dp)
1062 rayleigh_b_minus(i) = real(dot_product(rotation_minus(:, i), &
1063 matmul(hamiltonian_b, rotation_minus(:, i))), kind=
dp)
1065 energy_a_plus(:) = energy_a + fd_step*energy_direction(1:nbands)
1066 energy_a_minus(:) = energy_a - fd_step*energy_direction(1:nbands)
1067 energy_b_plus(:) = energy_b + fd_step*energy_direction(nbands + 1:nenergy)
1068 energy_b_minus(:) = energy_b - fd_step*energy_direction(nbands + 1:nenergy)
1069 energy_zero_a = fixed_n_mermin_value( &
1070 rayleigh_a, energy_a, weights, 1.65_dp, temperature, maxocc)
1071 energy_zero_b = fixed_n_mermin_value( &
1072 rayleigh_b, energy_b, weights, 0.95_dp, temperature, maxocc)
1073 energy_plus_a = fixed_n_mermin_value( &
1074 rayleigh_a_plus, energy_a_plus, weights, 1.65_dp, temperature, maxocc)
1075 energy_plus_b = fixed_n_mermin_value( &
1076 rayleigh_b_plus, energy_b_plus, weights, 0.95_dp, temperature, maxocc)
1077 energy_minus_a = fixed_n_mermin_value( &
1078 rayleigh_a_minus, energy_a_minus, weights, 1.65_dp, temperature, maxocc)
1079 energy_minus_b = fixed_n_mermin_value( &
1080 rayleigh_b_minus, energy_b_minus, weights, 0.95_dp, temperature, maxocc)
1081 energy_zero = energy_zero_a + energy_zero_b
1082 energy_plus = energy_plus_a + energy_plus_b
1083 energy_minus = energy_minus_a + energy_minus_b
1084 curvature_a = dot_product(rotation_direction, &
1085 matmul(rotation_hessian_a, rotation_direction)) - &
1086 2.0_dp*dot_product(energy_direction(1:nbands), &
1087 matmul(energy_hessian(1:nbands, 1:nbands), &
1088 matmul(rayleigh_response(1:nbands, :), &
1089 rotation_direction))) + &
1090 dot_product(energy_direction(1:nbands), &
1091 matmul(energy_hessian(1:nbands, 1:nbands), &
1092 energy_direction(1:nbands)))
1093 curvature_b = dot_product(rotation_direction, &
1094 matmul(rotation_hessian_b, rotation_direction)) - &
1095 2.0_dp*dot_product(energy_direction(nbands + 1:nenergy), &
1096 matmul(energy_hessian(nbands + 1:nenergy, &
1097 nbands + 1:nenergy), &
1098 matmul(rayleigh_response(nbands + 1:nenergy, :), &
1099 rotation_direction))) + &
1100 dot_product(energy_direction(nbands + 1:nenergy), &
1101 matmul(energy_hessian(nbands + 1:nenergy, nbands + 1:nenergy), &
1102 energy_direction(nbands + 1:nenergy)))
1103 curvature = curvature_a + curvature_b
1104 curvature_error = abs((energy_plus_a - 2.0_dp*energy_zero_a + energy_minus_a)/ &
1105 fd_step**2 - curvature_a)
1106 curvature_error = max( &
1108 abs((energy_plus_b - 2.0_dp*energy_zero_b + energy_minus_b)/fd_step**2 - curvature_b), &
1109 abs((energy_plus - 2.0_dp*energy_zero + energy_minus)/fd_step**2 - curvature))
1111 IF (schur_error > 3.0e-11_dp .OR. curvature_error > 5.0e-6_dp) nfail = nfail + 1
1112 IF (mynode == 0)
THEN
1113 WRITE (io_unit,
'(A,2(1X,ES13.6))')
"ROKS fixed-N rotation Schur errors:", &
1114 schur_error, curvature_error
1117 END SUBROUTINE test_roks_fixed_n_rotation_schur
1124 SUBROUTINE test_symmetric_abs_solve(mynode, nfail)
1125 INTEGER,
INTENT(IN) :: mynode
1126 INTEGER,
INTENT(INOUT) :: nfail
1129 REAL(KIND=
dp) :: error
1130 REAL(KIND=
dp),
DIMENSION(3) :: eigenvalues
1131 REAL(KIND=
dp),
DIMENSION(3, 2) :: expected, rhs, solution
1132 REAL(KIND=
dp),
DIMENSION(3, 3) :: absolute_matrix, matrix, vectors
1134 vectors(:, 1) = [0.8_dp, 0.6_dp, 0.0_dp]
1135 vectors(:, 2) = [-0.6_dp, 0.8_dp, 0.0_dp]
1136 vectors(:, 3) = [0.0_dp, 0.0_dp, 1.0_dp]
1137 eigenvalues(:) = [-0.4_dp, 1.7_dp, 0.25_dp]
1138 matrix(:, :) = matmul(vectors, matmul( &
1139 reshape([eigenvalues(1), 0.0_dp, 0.0_dp, 0.0_dp, eigenvalues(2), 0.0_dp, &
1140 0.0_dp, 0.0_dp, eigenvalues(3)], [3, 3]), transpose(vectors)))
1141 absolute_matrix(:, :) = matmul(vectors, matmul( &
1142 reshape([abs(eigenvalues(1)), 0.0_dp, 0.0_dp, 0.0_dp, abs(eigenvalues(2)), 0.0_dp, &
1143 0.0_dp, 0.0_dp, abs(eigenvalues(3))], [3, 3]), transpose(vectors)))
1144 rhs(:, 1) = [0.3_dp, -0.5_dp, 0.7_dp]
1145 rhs(:, 2) = [-0.2_dp, 0.4_dp, 0.1_dp]
1147 expected(:, :) = matmul(absolute_matrix, solution)
1148 error = maxval(abs(expected - rhs))
1149 IF (.NOT. valid .OR. error > 2.0e-13_dp) nfail = nfail + 1
1151 eigenvalues(:) = [-0.4_dp, 1.7_dp, 1.0e-12_dp]
1152 matrix(:, :) = matmul(vectors, matmul( &
1153 reshape([eigenvalues(1), 0.0_dp, 0.0_dp, 0.0_dp, eigenvalues(2), 0.0_dp, &
1154 0.0_dp, 0.0_dp, eigenvalues(3)], [3, 3]), transpose(vectors)))
1155 rhs(:, 1) = [0.3_dp, -0.5_dp, 0.7_dp]
1156 rhs(:, 2) = [-0.2_dp, 0.4_dp, 0.1_dp]
1158 expected(:, :) = rhs(:, :)
1159 expected(3, :) = 0.0_dp
1160 absolute_matrix(:, :) = matmul(vectors(:, 1:2), matmul( &
1161 reshape([abs(eigenvalues(1)), 0.0_dp, 0.0_dp, abs(eigenvalues(2))], [2, 2]), &
1162 transpose(vectors(:, 1:2))))
1163 error = max(error, maxval(abs(matmul(absolute_matrix, solution) - expected)))
1164 IF (.NOT. valid .OR. error > 2.0e-13_dp .OR. maxval(abs(solution(3, :))) > 2.0e-13_dp)
THEN
1167 IF (mynode == 0)
WRITE (io_unit,
'(A,1X,ES13.6)')
"symmetric absolute solve error:", error
1169 END SUBROUTINE test_symmetric_abs_solve
1176 SUBROUTINE test_projected_response_update(mynode, nfail)
1177 INTEGER,
INTENT(IN) :: mynode
1178 INTEGER,
INTENT(INOUT) :: nfail
1181 REAL(KIND=
dp) :: error, preservation_error
1182 REAL(KIND=
dp),
DIMENSION(2) :: coefficients, gradient, residual
1183 REAL(KIND=
dp),
DIMENSION(2, 2) :: correction, reference, total
1185 reference(:, :) = reshape([4.0_dp, 0.7_dp, 0.7_dp, 2.5_dp], [2, 2])
1186 correction(:, :) = 0.0_dp
1188 preservation_error = maxval(abs(coefficients - [1.0_dp, 0.0_dp]))
1189 IF (.NOT. valid .OR. preservation_error > 1.0e-12_dp) nfail = nfail + 1
1191 correction(:, :) = reshape([0.8_dp, -0.3_dp, -0.3_dp, 0.4_dp], [2, 2])
1192 gradient(:) = [1.2_dp, -0.4_dp]
1194 reference, correction, coefficients, valid, projected_gradient=gradient)
1195 total(:, :) = reference + correction
1196 residual(:) = matmul(total, coefficients) - gradient
1197 error = maxval(abs(residual))
1198 IF (.NOT. valid .OR. error > 1.0e-12_dp) nfail = nfail + 1
1200 correction(:, :) = reshape([-8.0_dp, 0.0_dp, 0.0_dp, 0.0_dp], [2, 2])
1202 IF (valid) nfail = nfail + 1
1203 IF (mynode == 0)
WRITE (io_unit,
'(A,2(1X,ES14.6))') &
1204 "projected response preservation/residual errors:", preservation_error, error
1206 END SUBROUTINE test_projected_response_update
1213 SUBROUTINE test_symmetric_sr1_update(mynode, nfail)
1214 INTEGER,
INTENT(IN) :: mynode
1215 INTEGER,
INTENT(INOUT) :: nfail
1218 REAL(KIND=
dp) :: rejected_error, secant_error, &
1220 REAL(KIND=
dp),
DIMENSION(3) :: orthogonal_residual, response, step
1221 REAL(KIND=
dp),
DIMENSION(3, 3) :: matrix, updated
1223 matrix(:, :) = 0.0_dp
1224 matrix(1, 1) = 1.0_dp
1225 matrix(2, 2) = 2.0_dp
1226 matrix(3, 3) = 3.0_dp
1227 step(:) = [0.3_dp, -0.4_dp, 0.2_dp]
1228 response(:) = [0.0_dp, -0.3_dp, 0.8_dp]
1230 secant_error = maxval(abs(matmul(updated, step) - response))
1231 symmetry_error = maxval(abs(updated - transpose(updated)))
1232 IF (.NOT. valid .OR. secant_error > 2.0e-14_dp .OR. symmetry_error > 2.0e-14_dp)
THEN
1236 orthogonal_residual(:) = [0.4_dp, 0.3_dp, 0.0_dp]
1237 response(:) = matmul(matrix, step) + orthogonal_residual
1239 rejected_error = maxval(abs(updated - matrix))
1240 IF (valid .OR. rejected_error > 2.0e-14_dp) nfail = nfail + 1
1241 IF (mynode == 0)
WRITE (io_unit,
'(A,3(1X,ES13.6))') &
1242 "symmetric SR1 secant/symmetry/rejection errors:", &
1243 secant_error, symmetry_error, rejected_error
1245 END SUBROUTINE test_symmetric_sr1_update
1252 SUBROUTINE test_density_secant_hessian(mynode, nfail)
1253 INTEGER,
INTENT(IN) :: mynode
1254 INTEGER,
INTENT(INOUT) :: nfail
1256 INTEGER,
PARAMETER :: n = 3, nmode = 2
1257 REAL(KIND=
dp),
PARAMETER :: secant_position = 0.4_dp
1259 COMPLEX(KIND=dp),
DIMENSION(n, n) :: density_step, hamiltonian_step, unitary
1260 COMPLEX(KIND=dp),
DIMENSION(n, n, nmode) :: density_modes, transformed_modes
1261 LOGICAL :: calibrated_valid, rejected_valid, valid
1262 REAL(KIND=
dp) :: calibrated_error, density_norm, direct_error, gauge_error, overlap_error, &
1263 rejected_error, response_work, sign_error
1264 REAL(KIND=
dp),
DIMENSION(nmode) :: density_overlap, response_overlap
1265 REAL(KIND=
dp),
DIMENSION(nmode, nmode) :: calibrated, correction, &
1266 correction_gauge, correction_overlap, &
1269 density_step(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
1270 density_step(1, 1) = cmplx(0.30_dp, 0.0_dp, kind=
dp)
1271 density_step(2, 2) = cmplx(-0.18_dp, 0.0_dp, kind=
dp)
1272 density_step(3, 3) = cmplx(-0.12_dp, 0.0_dp, kind=
dp)
1273 density_step(1, 2) = cmplx(0.07_dp, -0.11_dp, kind=
dp)
1274 density_step(2, 1) = conjg(density_step(1, 2))
1275 density_step(1, 3) = cmplx(-0.04_dp, 0.05_dp, kind=
dp)
1276 density_step(3, 1) = conjg(density_step(1, 3))
1278 hamiltonian_step(:, :) = -0.45_dp*density_step
1279 hamiltonian_step(2, 3) = cmplx(0.06_dp, 0.03_dp, kind=
dp)
1280 hamiltonian_step(3, 2) = conjg(hamiltonian_step(2, 3))
1281 density_modes(:, :, 1) = density_step
1282 density_modes(:, :, 2) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
1283 density_modes(1, 1, 2) = cmplx(-0.2_dp, 0.0_dp, kind=
dp)
1284 density_modes(2, 2, 2) = cmplx(0.1_dp, 0.0_dp, kind=
dp)
1285 density_modes(3, 3, 2) = cmplx(0.1_dp, 0.0_dp, kind=
dp)
1286 density_modes(1, 3, 2) = cmplx(0.03_dp, 0.08_dp, kind=
dp)
1287 density_modes(3, 1, 2) = conjg(density_modes(1, 3, 2))
1290 density_step, hamiltonian_step, density_modes, correction, valid, &
1291 density_norm, response_work)
1292 density_overlap(1) = density_norm
1293 density_overlap(2) = sum(real(conjg(density_step)*density_modes(:, :, 2), kind=
dp))
1294 response_overlap(1) = response_work
1295 response_overlap(2) = sum(real(conjg(hamiltonian_step)*density_modes(:, :, 2), kind=
dp))
1297 density_norm, response_work, density_overlap, response_overlap, correction_overlap, valid)
1299 expected(1, 1) = response_work
1300 expected(1, 2) = response_overlap(2)
1301 expected(2, 1) = response_overlap(2)
1302 expected(2, 2) = (2.0_dp*density_overlap(2)*response_overlap(2) - &
1303 response_work*density_overlap(2)**2/density_norm)/density_norm
1304 direct_error = maxval(abs(correction - expected))
1305 overlap_error = maxval(abs(correction_overlap - correction))
1306 sign_error = max(0.0_dp, correction(1, 1))
1309 density_norm, response_work, density_overlap, response_overlap, calibrated, &
1310 calibrated_valid, secant_mode=2, secant_position=secant_position)
1311 expected(1, 1) = response_work
1312 expected(1, 2) = response_work/secant_position
1313 expected(2, 1) = expected(1, 2)
1314 expected(2, 2) = response_work/secant_position**2
1315 calibrated_error = maxval(abs(calibrated - expected))
1317 density_norm, response_work, density_overlap, response_overlap, rejected, &
1318 rejected_valid, secant_mode=2, secant_position=0.0_dp)
1319 rejected_error = maxval(abs(rejected))
1321 unitary(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
1322 unitary(1, 1) = cmplx(sqrt(0.5_dp), 0.0_dp, kind=
dp)
1323 unitary(2, 1) = cmplx(0.0_dp, sqrt(0.5_dp), kind=
dp)
1324 unitary(1, 2) = cmplx(0.0_dp, sqrt(0.5_dp), kind=
dp)
1325 unitary(2, 2) = cmplx(sqrt(0.5_dp), 0.0_dp, kind=
dp)
1326 unitary(3, 3) = cmplx(1.0_dp, 0.0_dp, kind=
dp)
1327 density_step = matmul(conjg(transpose(unitary)), matmul(density_step, unitary))
1328 hamiltonian_step = matmul(conjg(transpose(unitary)), matmul(hamiltonian_step, unitary))
1329 transformed_modes(:, :, 1) = &
1330 matmul(conjg(transpose(unitary)), matmul(density_modes(:, :, 1), unitary))
1331 transformed_modes(:, :, 2) = &
1332 matmul(conjg(transpose(unitary)), matmul(density_modes(:, :, 2), unitary))
1334 density_step, hamiltonian_step, transformed_modes, correction_gauge, valid)
1335 gauge_error = maxval(abs(correction_gauge - correction))
1337 IF (.NOT. valid .OR. .NOT. calibrated_valid .OR. rejected_valid .OR. &
1338 direct_error > 2.0e-14_dp .OR. overlap_error > 2.0e-14_dp .OR. &
1339 gauge_error > 2.0e-14_dp .OR. sign_error > 2.0e-14_dp .OR. &
1340 calibrated_error > 2.0e-14_dp .OR. rejected_error > 2.0e-14_dp) nfail = nfail + 1
1341 IF (mynode == 0)
WRITE (io_unit,
'(A,6(1X,ES13.6))') &
1342 "density secant direct/overlap/gauge/sign/calibrated/rejected errors:", &
1343 direct_error, overlap_error, gauge_error, sign_error, calibrated_error, rejected_error
1345 END SUBROUTINE test_density_secant_hessian
1352 SUBROUTINE test_joint_spin_density_secant(mynode, nfail)
1353 INTEGER,
INTENT(IN) :: mynode
1354 INTEGER,
INTENT(INOUT) :: nfail
1356 INTEGER,
PARAMETER :: n = 2, nmode = 2, nspin = 2, &
1359 COMPLEX(KIND=dp),
DIMENSION(n, n, nmode, nspin) :: density_modes
1360 COMPLEX(KIND=dp),
DIMENSION(n, n, nspin) :: density_step, hamiltonian_step
1361 COMPLEX(KIND=dp),
DIMENSION(ntotal, ntotal) :: direct_density_step, &
1362 direct_hamiltonian_step
1363 COMPLEX(KIND=dp),
DIMENSION(ntotal, ntotal, nmode) :: direct_density_modes
1364 INTEGER :: first, ispin, last, mode
1365 LOGICAL :: direct_valid, joint_valid, spin_valid
1366 REAL(KIND=
dp) :: coupling_size, density_norm, &
1367 direct_error, response_work
1368 REAL(KIND=
dp),
DIMENSION(nmode) :: density_overlap, response_overlap
1369 REAL(KIND=
dp),
DIMENSION(nmode, nmode) :: direct_correction, joint_correction, &
1370 separate_correction, spin_correction
1372 density_step(:, :, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
1373 density_step(1, 1, 1) = 0.31_dp
1374 density_step(2, 2, 1) = -0.31_dp
1375 density_step(1, 2, 1) = cmplx(0.08_dp, -0.04_dp, kind=
dp)
1376 density_step(2, 1, 1) = conjg(density_step(1, 2, 1))
1377 density_step(1, 1, 2) = -0.19_dp
1378 density_step(2, 2, 2) = 0.19_dp
1379 density_step(1, 2, 2) = cmplx(-0.05_dp, 0.06_dp, kind=
dp)
1380 density_step(2, 1, 2) = conjg(density_step(1, 2, 2))
1382 hamiltonian_step(:, :, 1) = 0.67_dp*density_step(:, :, 1)
1383 hamiltonian_step(1, 2, 1) = hamiltonian_step(1, 2, 1) + cmplx(-0.03_dp, 0.09_dp, kind=
dp)
1384 hamiltonian_step(2, 1, 1) = conjg(hamiltonian_step(1, 2, 1))
1385 hamiltonian_step(:, :, 2) = -0.43_dp*density_step(:, :, 2)
1386 hamiltonian_step(1, 2, 2) = hamiltonian_step(1, 2, 2) + cmplx(0.07_dp, 0.02_dp, kind=
dp)
1387 hamiltonian_step(2, 1, 2) = conjg(hamiltonian_step(1, 2, 2))
1389 density_modes(:, :, :, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
1390 density_modes(1, 1, 1, 1) = 0.21_dp
1391 density_modes(2, 2, 1, 1) = -0.21_dp
1392 density_modes(1, 2, 1, 1) = cmplx(0.04_dp, 0.03_dp, kind=
dp)
1393 density_modes(2, 1, 1, 1) = conjg(density_modes(1, 2, 1, 1))
1394 density_modes(1, 1, 2, 1) = -0.13_dp
1395 density_modes(2, 2, 2, 1) = 0.13_dp
1396 density_modes(1, 2, 2, 1) = cmplx(-0.02_dp, 0.05_dp, kind=
dp)
1397 density_modes(2, 1, 2, 1) = conjg(density_modes(1, 2, 2, 1))
1398 density_modes(1, 1, 1, 2) = -0.17_dp
1399 density_modes(2, 2, 1, 2) = 0.17_dp
1400 density_modes(1, 2, 1, 2) = cmplx(0.06_dp, -0.01_dp, kind=
dp)
1401 density_modes(2, 1, 1, 2) = conjg(density_modes(1, 2, 1, 2))
1402 density_modes(1, 1, 2, 2) = 0.09_dp
1403 density_modes(2, 2, 2, 2) = -0.09_dp
1404 density_modes(1, 2, 2, 2) = cmplx(0.03_dp, 0.04_dp, kind=
dp)
1405 density_modes(2, 1, 2, 2) = conjg(density_modes(1, 2, 2, 2))
1407 direct_density_step(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
1408 direct_hamiltonian_step(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
1409 direct_density_modes(:, :, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
1410 density_norm = 0.0_dp
1411 response_work = 0.0_dp
1412 density_overlap(:) = 0.0_dp
1413 response_overlap(:) = 0.0_dp
1414 separate_correction(:, :) = 0.0_dp
1417 first = (ispin - 1)*n + 1
1419 direct_density_step(first:last, first:last) = density_step(:, :, ispin)
1420 direct_hamiltonian_step(first:last, first:last) = hamiltonian_step(:, :, ispin)
1421 direct_density_modes(first:last, first:last, :) = density_modes(:, :, :, ispin)
1422 density_norm = density_norm + &
1423 sum(real(conjg(density_step(:, :, ispin))* &
1424 density_step(:, :, ispin), kind=
dp))
1425 response_work = response_work + &
1426 sum(real(conjg(density_step(:, :, ispin))* &
1427 hamiltonian_step(:, :, ispin), kind=
dp))
1429 density_overlap(mode) = density_overlap(mode) + &
1430 sum(real(conjg(density_step(:, :, ispin))* &
1431 density_modes(:, :, mode, ispin), kind=
dp))
1432 response_overlap(mode) = response_overlap(mode) + &
1433 sum(real(conjg(hamiltonian_step(:, :, ispin))* &
1434 density_modes(:, :, mode, ispin), kind=
dp))
1437 density_step(:, :, ispin), hamiltonian_step(:, :, ispin), &
1438 density_modes(:, :, :, ispin), spin_correction, direct_valid)
1439 spin_valid = spin_valid .AND. direct_valid
1440 separate_correction = separate_correction + spin_correction
1444 direct_density_step, direct_hamiltonian_step, direct_density_modes, &
1445 direct_correction, direct_valid)
1447 density_norm, response_work, density_overlap, response_overlap, &
1448 joint_correction, joint_valid)
1449 direct_error = maxval(abs(joint_correction - direct_correction))
1450 coupling_size = maxval(abs(joint_correction - separate_correction))
1452 IF (.NOT. direct_valid .OR. .NOT. joint_valid .OR. .NOT. spin_valid .OR. &
1453 direct_error > 3.0e-14_dp .OR. coupling_size < 1.0e-5_dp) nfail = nfail + 1
1454 IF (mynode == 0)
WRITE (io_unit,
'(A,2(1X,ES13.6))') &
1455 "joint-spin density secant direct error/coupling:", direct_error, coupling_size
1457 END SUBROUTINE test_joint_spin_density_secant
1464 SUBROUTINE test_density_tangent(mynode, nfail)
1465 INTEGER,
INTENT(IN) :: mynode
1466 INTEGER,
INTENT(INOUT) :: nfail
1468 INTEGER,
PARAMETER :: nbands = 3, nrotation = 6
1469 REAL(KIND=
dp),
PARAMETER :: fd_step = 2.0e-6_dp, &
1470 kpoint_weight = 0.625_dp
1472 COMPLEX(KIND=dp),
DIMENSION(nbands, nbands) :: density_minus, density_plus, density_tangent, &
1473 direction_generator, generator, rotation, rotation_minus, rotation_plus, weighted_rotation
1475 REAL(KIND=
dp) :: error, trace_error
1476 REAL(KIND=
dp),
DIMENSION(nbands) :: occupation, weighted_occupation_step
1477 REAL(KIND=
dp),
DIMENSION(nrotation) :: rotation_step
1479 generator(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
1480 generator(1, 2) = cmplx(0.17_dp, -0.09_dp, kind=
dp)
1481 generator(2, 1) = -conjg(generator(1, 2))
1482 generator(1, 3) = cmplx(-0.06_dp, 0.11_dp, kind=
dp)
1483 generator(3, 1) = -conjg(generator(1, 3))
1484 generator(2, 3) = cmplx(0.08_dp, 0.04_dp, kind=
dp)
1485 generator(3, 2) = -conjg(generator(2, 3))
1486 occupation(:) = [1.72_dp, 0.83_dp, 0.31_dp]
1487 rotation_step(:) = [0.21_dp, -0.14_dp, -0.08_dp, 0.17_dp, 0.11_dp, 0.06_dp]
1488 weighted_occupation_step(:) = [-0.037_dp, 0.052_dp, -0.015_dp]
1491 generator, occupation, kpoint_weight, rotation_step, weighted_occupation_step, &
1492 density_tangent, difference_step=fd_step)
1494 direction_generator(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
1496 DO i = 1, nbands - 1
1497 DO j = i + 1, nbands
1499 direction_generator(i, j) = cmplx(rotation_step(r), 0.0_dp, kind=
dp)
1500 direction_generator(j, i) = -direction_generator(i, j)
1502 direction_generator(i, j) = direction_generator(i, j) + &
1503 cmplx(0.0_dp, rotation_step(r), kind=
dp)
1504 direction_generator(j, i) = direction_generator(j, i) + &
1505 cmplx(0.0_dp, rotation_step(r), kind=
dp)
1508 rotation = dense_antihermitian_exp(generator)
1509 rotation_plus = dense_antihermitian_exp(generator + fd_step*direction_generator)
1510 rotation_minus = dense_antihermitian_exp(generator - fd_step*direction_generator)
1511 weighted_rotation(:, :) = rotation_plus
1513 weighted_rotation(:, j) = &
1514 (kpoint_weight*occupation(j) + fd_step*weighted_occupation_step(j))* &
1515 weighted_rotation(:, j)
1517 density_plus(:, :) = matmul(weighted_rotation, conjg(transpose(rotation_plus)))
1518 weighted_rotation(:, :) = rotation_minus
1520 weighted_rotation(:, j) = &
1521 (kpoint_weight*occupation(j) - fd_step*weighted_occupation_step(j))* &
1522 weighted_rotation(:, j)
1524 density_minus(:, :) = matmul(weighted_rotation, conjg(transpose(rotation_minus)))
1525 density_plus(:, :) = matmul(conjg(transpose(rotation)), &
1526 matmul((density_plus - density_minus)/(2.0_dp*fd_step), rotation))
1527 error = maxval(abs(density_tangent - density_plus))
1528 trace_error = abs(real(sum([(density_tangent(i, i), i=1, nbands)]), kind=
dp) - &
1529 sum(weighted_occupation_step))
1531 IF (error > 3.0e-9_dp .OR. trace_error > 3.0e-10_dp) nfail = nfail + 1
1532 IF (mynode == 0)
WRITE (io_unit,
'(A,2(1X,ES13.6))') &
1533 "finite complex density tangent errors:", error, trace_error
1535 END SUBROUTINE test_density_tangent
1542 SUBROUTINE test_density_secant_moving_subspace(mynode, nfail)
1543 INTEGER,
INTENT(IN) :: mynode
1544 INTEGER,
INTENT(INOUT) :: nfail
1546 INTEGER,
PARAMETER :: nao = 4, nbands = 3, nmode = 2
1547 REAL(KIND=
dp),
PARAMETER :: weight = 0.625_dp
1549 COMPLEX(KIND=dp),
DIMENSION(nao, nao) :: density_step, hamiltonian_step
1550 COMPLEX(KIND=dp),
DIMENSION(nao, nao, nmode) :: density_modes_ao
1551 COMPLEX(KIND=dp),
DIMENSION(nao, nbands) :: c0, c1
1552 COMPLEX(KIND=dp),
DIMENSION(nbands, nbands) :: h0, h1, overlap
1553 COMPLEX(KIND=dp),
DIMENSION(nbands, nbands, nmode) :: density_modes
1556 REAL(KIND=
dp) :: density_norm, density_norm_ref, error, &
1557 response_work, response_work_ref
1558 REAL(KIND=
dp),
DIMENSION(nbands) :: occupation0, occupation1
1559 REAL(KIND=
dp),
DIMENSION(nmode) :: density_overlap, density_overlap_ref, &
1560 response_overlap, response_overlap_ref
1562 c0(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
1567 c1(1, 1) = cos(0.31_dp)
1568 c1(4, 1) = sin(0.31_dp)
1569 c1(2, 2) = cos(0.23_dp)
1570 c1(3, 2) = cmplx(0.0_dp, sin(0.23_dp), kind=
dp)
1571 c1(2, 3) = cmplx(0.0_dp, sin(0.23_dp), kind=
dp)
1572 c1(3, 3) = cos(0.23_dp)
1573 occupation0(:) = [1.73_dp, 0.82_dp, 0.82_dp]
1574 occupation1(:) = [1.61_dp, 0.91_dp, 0.76_dp]
1576 hamiltonian_step(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
1577 hamiltonian_step(1, 1) = 0.21_dp
1578 hamiltonian_step(2, 2) = -0.17_dp
1579 hamiltonian_step(3, 3) = 0.09_dp
1580 hamiltonian_step(4, 4) = -0.04_dp
1581 hamiltonian_step(1, 4) = cmplx(0.07_dp, -0.03_dp, kind=
dp)
1582 hamiltonian_step(4, 1) = conjg(hamiltonian_step(1, 4))
1583 hamiltonian_step(2, 3) = cmplx(-0.05_dp, 0.08_dp, kind=
dp)
1584 hamiltonian_step(3, 2) = conjg(hamiltonian_step(2, 3))
1585 density_modes(:, :, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
1586 density_modes(1, 1, 1) = 0.13_dp
1587 density_modes(2, 2, 1) = -0.08_dp
1588 density_modes(3, 3, 1) = -0.05_dp
1589 density_modes(1, 2, 2) = cmplx(0.04_dp, -0.06_dp, kind=
dp)
1590 density_modes(2, 1, 2) = conjg(density_modes(1, 2, 2))
1592 overlap(:, :) = matmul(conjg(transpose(c0)), c1)
1594 CALL reference_project_operator(c0, hamiltonian_step, h0)
1595 CALL reference_project_operator(c1, hamiltonian_step, h1)
1597 overlap, occupation0, occupation1, h0, h1, density_modes, weight, density_norm, &
1598 response_work, density_overlap, response_overlap, valid)
1600 density_step(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
1602 density_step = density_step + weight*occupation1(i)* &
1603 spread(c1(:, i), dim=2, ncopies=nao)* &
1604 spread(conjg(c1(:, i)), dim=1, ncopies=nao) - &
1605 weight*occupation0(i)* &
1606 spread(c0(:, i), dim=2, ncopies=nao)* &
1607 spread(conjg(c0(:, i)), dim=1, ncopies=nao)
1610 CALL reference_transform_density_mode(c1, density_modes(:, :, i), density_modes_ao(:, :, i))
1611 density_overlap_ref(i) = &
1612 reference_frobenius_product_real(density_step, density_modes_ao(:, :, i))/weight
1613 response_overlap_ref(i) = &
1614 reference_frobenius_product_real(hamiltonian_step, density_modes_ao(:, :, i))
1616 density_norm_ref = reference_frobenius_product_real(density_step, density_step)/weight
1617 response_work_ref = reference_frobenius_product_real(density_step, hamiltonian_step)
1618 error = max(abs(density_norm - density_norm_ref), abs(response_work - response_work_ref))
1619 error = max(error, maxval(abs(density_overlap - density_overlap_ref)))
1620 error = max(error, maxval(abs(response_overlap - response_overlap_ref)))
1622 IF (.NOT. valid .OR. error > 3.0e-13_dp) nfail = nfail + 1
1623 IF (mynode == 0)
WRITE (io_unit,
'(A,1X,ES13.6)') &
1624 "moving-subspace density secant error:", error
1626 END SUBROUTINE test_density_secant_moving_subspace
1634 SUBROUTINE reference_project_operator(orbitals, hamiltonian, projected)
1635 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: orbitals, hamiltonian
1636 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: projected
1638 COMPLEX(KIND=dp) :: value
1639 INTEGER :: i, j, mu, nu
1641 DO j = 1,
SIZE(orbitals, 2)
1642 DO i = 1,
SIZE(orbitals, 2)
1643 value = cmplx(0.0_dp, 0.0_dp, kind=
dp)
1644 DO nu = 1,
SIZE(orbitals, 1)
1645 DO mu = 1,
SIZE(orbitals, 1)
1646 value =
value + conjg(orbitals(mu, i))*hamiltonian(mu, nu)*orbitals(nu, j)
1649 projected(i, j) =
value
1653 END SUBROUTINE reference_project_operator
1661 SUBROUTINE reference_transform_density_mode(orbitals, mode, transformed)
1662 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: orbitals, mode
1663 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: transformed
1665 COMPLEX(KIND=dp) :: value
1666 INTEGER :: i, j, m, n
1668 DO j = 1,
SIZE(orbitals, 1)
1669 DO i = 1,
SIZE(orbitals, 1)
1670 value = cmplx(0.0_dp, 0.0_dp, kind=
dp)
1671 DO n = 1,
SIZE(orbitals, 2)
1672 DO m = 1,
SIZE(orbitals, 2)
1673 value =
value + orbitals(i, m)*mode(m, n)*conjg(orbitals(j, n))
1676 transformed(i, j) =
value
1680 END SUBROUTINE reference_transform_density_mode
1688 FUNCTION reference_frobenius_product_real(matrix_a, matrix_b)
RESULT(value)
1689 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: matrix_a, matrix_b
1690 REAL(KIND=
dp) ::
value
1692 value = sum(real(matrix_a, kind=
dp)*real(matrix_b, kind=
dp) + &
1693 aimag(matrix_a)*aimag(matrix_b))
1695 END FUNCTION reference_frobenius_product_real
1705 FUNCTION finite_rotation_energy(rotation, hamiltonian, occupation, kpoint_weight)
RESULT(energy)
1706 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: rotation, hamiltonian
1707 REAL(KIND=
dp),
DIMENSION(:),
INTENT(IN) :: occupation
1708 REAL(KIND=
dp),
INTENT(IN) :: kpoint_weight
1709 REAL(KIND=
dp) :: energy
1714 DO i = 1,
SIZE(occupation)
1715 energy = energy + kpoint_weight*occupation(i)* &
1716 REAL(DOT_PRODUCT(rotation(:, i), &
1717 MATMUL(hamiltonian, rotation(:, i))), KIND=
dp)
1720 END FUNCTION finite_rotation_energy
1732 SUBROUTINE fixed_n_fermi_occupations(energies, weights, target_electrons, temperature, &
1733 maxocc, occupation, mu)
1734 REAL(KIND=
dp),
DIMENSION(:),
INTENT(IN) :: energies, weights
1735 REAL(KIND=
dp),
INTENT(IN) :: target_electrons, temperature, maxocc
1736 REAL(KIND=
dp),
DIMENSION(:),
INTENT(OUT) :: occupation
1737 REAL(KIND=
dp),
INTENT(OUT) :: mu
1739 INTEGER :: i, iteration
1740 REAL(KIND=
dp) :: high, low, number
1742 low = minval(energies) - 80.0_dp*temperature
1743 high = maxval(energies) + 80.0_dp*temperature
1744 DO iteration = 1, 160
1745 mu = 0.5_dp*(low + high)
1747 DO i = 1,
SIZE(energies)
1748 occupation(i) = fermi_occupation(energies(i), mu, temperature, maxocc)
1749 number = number + weights(i)*occupation(i)
1751 IF (number < target_electrons)
THEN
1757 mu = 0.5_dp*(low + high)
1758 DO i = 1,
SIZE(energies)
1759 occupation(i) = fermi_occupation(energies(i), mu, temperature, maxocc)
1762 END SUBROUTINE fixed_n_fermi_occupations
1772 PURE FUNCTION fermi_occupation(energy, mu, temperature, maxocc)
RESULT(occupation)
1773 REAL(KIND=
dp),
INTENT(IN) :: energy, mu, temperature, maxocc
1774 REAL(KIND=
dp) :: occupation
1778 x = (energy - mu)/temperature
1779 IF (x > 40.0_dp)
THEN
1780 occupation = maxocc*exp(-x)
1781 ELSE IF (x < -40.0_dp)
THEN
1782 occupation = maxocc*(1.0_dp - exp(x))
1784 occupation = maxocc/(1.0_dp + exp(x))
1787 END FUNCTION fermi_occupation
1799 FUNCTION fixed_n_mermin_value(rayleigh, energies, weights, target_electrons, &
1800 temperature, maxocc)
RESULT(value)
1801 REAL(KIND=
dp),
DIMENSION(:),
INTENT(IN) :: rayleigh, energies, weights
1802 REAL(KIND=
dp),
INTENT(IN) :: target_electrons, temperature, maxocc
1803 REAL(KIND=
dp) ::
value
1806 REAL(KIND=
dp) :: mu, p
1807 REAL(KIND=
dp),
DIMENSION(SIZE(energies)) :: occupation
1809 CALL fixed_n_fermi_occupations(energies, weights, target_electrons, temperature, &
1810 maxocc, occupation, mu)
1812 DO i = 1,
SIZE(energies)
1813 p = max(epsilon(1.0_dp), min(1.0_dp - epsilon(1.0_dp), occupation(i)/maxocc))
1814 value =
value + weights(i)*(occupation(i)*rayleigh(i) + &
1815 temperature*maxocc*(p*log(p) + (1.0_dp - p)*log(1.0_dp - p)))
1818 END FUNCTION fixed_n_mermin_value
1829 SUBROUTINE fixed_n_spectral_projector(hamiltonian, weights, target_electrons, temperature, &
1831 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: hamiltonian
1832 REAL(KIND=
dp),
DIMENSION(:),
INTENT(IN) :: weights
1833 REAL(KIND=
dp),
INTENT(IN) :: target_electrons, temperature, maxocc
1834 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: projector
1836 COMPLEX(KIND=dp),
DIMENSION(SIZE(hamiltonian, 1), &
SIZE(hamiltonian, 1)) :: vectors, weighted_vectors
1839 REAL(KIND=
dp),
DIMENSION(SIZE(hamiltonian, 1)) :: eigenvalues, occupation
1842 CALL fixed_n_fermi_occupations(eigenvalues, weights, target_electrons, temperature, &
1843 maxocc, occupation, mu)
1844 weighted_vectors(:, :) = vectors(:, :)
1845 DO i = 1,
SIZE(eigenvalues)
1846 weighted_vectors(:, i) = weights(i)*occupation(i)*weighted_vectors(:, i)
1848 projector(:, :) = matmul(weighted_vectors, conjg(transpose(vectors)))
1850 END SUBROUTINE fixed_n_spectral_projector
1857 SUBROUTINE test_real_rotation_frechet(para_env, nfail)
1859 INTEGER,
INTENT(INOUT) :: nfail
1861 INTEGER,
PARAMETER :: m = 3
1864 INTEGER,
DIMENSION(:),
POINTER :: col_dist, col_size, row_dist, row_size
1865 INTEGER,
DIMENSION(:, :),
POINTER :: pgrid
1867 REAL(kind=
dp) :: error, fd_slope, hstep, predicted
1868 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: block
1869 REAL(kind=
dp),
DIMENSION(m),
TARGET :: rotation_evals
1870 REAL(kind=
dp),
DIMENSION(m, m) :: dedu, direction, generator, gradient, &
1871 rotation_minus, rotation_plus
1874 TYPE(
dbcsr_type),
DIMENSION(7),
TARGET :: matrices
1878 NULLIFY (blacs_env, local_para_env)
1879 generator(:, :) = 0.0_dp
1880 generator(1, 2) = 0.23_dp
1881 generator(2, 1) = -generator(1, 2)
1882 generator(1, 3) = -0.11_dp
1883 generator(3, 1) = -generator(1, 3)
1884 generator(2, 3) = 0.17_dp
1885 generator(3, 2) = -generator(2, 3)
1887 direction(:, :) = 0.0_dp
1888 direction(1, 2) = -0.09_dp
1889 direction(2, 1) = -direction(1, 2)
1890 direction(1, 3) = 0.14_dp
1891 direction(3, 1) = -direction(1, 3)
1892 direction(2, 3) = 0.06_dp
1893 direction(3, 2) = -direction(2, 3)
1895 dedu = reshape([0.31_dp, -0.27_dp, 0.08_dp, &
1896 0.19_dp, 0.42_dp, -0.16_dp, &
1897 -0.07_dp, 0.21_dp, 0.35_dp], [m, m])
1899 ALLOCATE (local_para_env)
1902 ALLOCATE (pgrid(0:0, 0:0), row_dist(1), col_dist(1), row_size(1), col_size(1))
1909 row_dist=row_dist, col_dist=col_dist)
1910 DO i = 1,
SIZE(matrices)
1911 CALL create_one_block(matrices(i),
'real_rotation', dist, row_size, col_size)
1916 rotation_env%para_env => local_para_env
1917 rotation_env%blacs_env => blacs_env
1918 rotation_env%rot_mat_u => matrices(1)
1919 rotation_env%rot_mat_x => matrices(2)
1920 rotation_env%rot_mat_dedu => matrices(3)
1921 rotation_env%rot_mat_gx => matrices(4)
1922 rotation_env%rot_mat_evec_re => matrices(5)
1923 rotation_env%rot_mat_evec_im => matrices(6)
1924 rotation_env%matrix_buf1 => matrices(7)
1925 rotation_env%rot_mat_evals => rotation_evals
1929 gradient(:, :) = 0.0_dp
1931 IF (found) gradient = block
1934 rotation_plus = real(dense_antihermitian_exp( &
1935 cmplx(generator + hstep*direction, 0.0_dp, kind=
dp)), kind=
dp)
1936 rotation_minus = real(dense_antihermitian_exp( &
1937 cmplx(generator - hstep*direction, 0.0_dp, kind=
dp)), kind=
dp)
1938 fd_slope = sum(dedu*(rotation_plus - rotation_minus))/(2.0_dp*hstep)
1939 predicted = 0.5_dp*sum(gradient*direction)
1940 error = abs(predicted - fd_slope)
1941 IF (error > 5.0e-8_dp) nfail = nfail + 1
1942 IF (para_env%is_source())
THEN
1943 WRITE (io_unit,
'(A,3(1X,ES13.6))')
'real finite rotation slope fd/predicted/error', &
1944 fd_slope, predicted, error
1947 DO i = 1,
SIZE(matrices)
1951 DEALLOCATE (pgrid, row_dist, col_dist, row_size, col_size)
1955 END SUBROUTINE test_real_rotation_frechet
1962 SUBROUTINE test_complex_ref_rotation(para_env, nfail)
1964 INTEGER,
INTENT(INOUT) :: nfail
1966 COMPLEX(KIND=dp),
DIMENSION(k, k) :: direction_a, generator, gradient_a, &
1967 inverse_sqrt, rotation
1968 COMPLEX(KIND=dp),
DIMENSION(n, k) :: c_dense, c_reference, direction_x, &
1969 gradient_x, hc_dense, q_dense, x_dense
1970 COMPLEX(KIND=dp),
DIMENSION(n, n) :: hamiltonian, overlap
1972 INTEGER,
DIMENSION(:),
POINTER :: col_dist, col_k, col_n, row_dist, row_k, &
1974 INTEGER,
DIMENSION(:, :),
POINTER :: pgrid
1975 REAL(KIND=
dp) :: error_c, error_ref, error_rot, fd_ref, &
1976 fd_rot, hstep, predicted_ref, &
1978 REAL(KIND=
dp),
DIMENSION(k) :: occupation
1979 REAL(KIND=
dp),
DIMENSION(k),
TARGET :: rotation_evals
1982 TYPE(
dbcsr_type),
DIMENSION(10),
TARGET :: rot_matrix
1983 TYPE(
dbcsr_type),
DIMENSION(2),
TARGET :: nk_buffer
1984 TYPE(
dbcsr_type),
DIMENSION(3),
TARGET :: nonsym_buffer
1985 TYPE(
dbcsr_type),
DIMENSION(4),
TARGET :: sym_buffer
1986 TYPE(
dbcsr_type),
POINTER :: c_im_p, c_re_p, hc_im_p, hc_re_p, &
1988 TYPE(
dbcsr_type),
TARGET :: c_im, c_re, f_im, f_re, g_im, g_re, &
1989 hc_im, hc_re, s_im, s_re, sx_im, &
1994 NULLIFY (blacs_env, c_im_p, c_re_p, hc_im_p, hc_re_p, local_para_env, &
1997 x_dense(:, 1) = [cmplx(1.05_dp, 0.12_dp, kind=
dp), cmplx(0.18_dp, -0.27_dp, kind=
dp), &
1998 cmplx(-0.14_dp, 0.16_dp, kind=
dp)]
1999 x_dense(:, 2) = [cmplx(0.26_dp, 0.31_dp, kind=
dp), cmplx(0.94_dp, -0.17_dp, kind=
dp), &
2000 cmplx(0.21_dp, 0.13_dp, kind=
dp)]
2001 direction_x(:, 1) = [cmplx(0.11_dp, -0.07_dp, kind=
dp), cmplx(-0.16_dp, 0.09_dp, kind=
dp), &
2002 cmplx(0.05_dp, 0.14_dp, kind=
dp)]
2003 direction_x(:, 2) = [cmplx(-0.08_dp, 0.15_dp, kind=
dp), cmplx(0.13_dp, 0.04_dp, kind=
dp), &
2004 cmplx(-0.10_dp, -0.06_dp, kind=
dp)]
2006 generator(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2007 generator(1, 1) = cmplx(0.0_dp, 0.19_dp, kind=
dp)
2008 generator(2, 2) = cmplx(0.0_dp, -0.08_dp, kind=
dp)
2009 generator(1, 2) = cmplx(0.23_dp, -0.11_dp, kind=
dp)
2010 generator(2, 1) = -conjg(generator(1, 2))
2011 direction_a(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2012 direction_a(1, 1) = cmplx(0.0_dp, -0.07_dp, kind=
dp)
2013 direction_a(2, 2) = cmplx(0.0_dp, 0.05_dp, kind=
dp)
2014 direction_a(1, 2) = cmplx(-0.09_dp, 0.06_dp, kind=
dp)
2015 direction_a(2, 1) = -conjg(direction_a(1, 2))
2017 hamiltonian(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2018 hamiltonian(1, 1) = cmplx(0.65_dp, 0.0_dp, kind=
dp)
2019 hamiltonian(2, 2) = cmplx(-0.35_dp, 0.0_dp, kind=
dp)
2020 hamiltonian(3, 3) = cmplx(1.15_dp, 0.0_dp, kind=
dp)
2021 hamiltonian(1, 2) = cmplx(0.18_dp, 0.12_dp, kind=
dp)
2022 hamiltonian(1, 3) = cmplx(-0.09_dp, 0.07_dp, kind=
dp)
2023 hamiltonian(2, 3) = cmplx(0.14_dp, -0.17_dp, kind=
dp)
2026 hamiltonian(j, i) = conjg(hamiltonian(i, j))
2029 overlap(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2031 overlap(i, i) = cmplx(1.0_dp, 0.0_dp, kind=
dp)
2033 occupation = [1.0_dp, 0.37_dp]
2035 CALL dense_inverse_sqrt(matmul(conjg(transpose(x_dense)), x_dense), inverse_sqrt)
2036 q_dense = matmul(x_dense, inverse_sqrt)
2037 rotation = dense_antihermitian_exp(generator)
2038 c_reference = matmul(q_dense, rotation)
2040 ALLOCATE (local_para_env)
2044 ALLOCATE (pgrid(0:0, 0:0), row_dist(1), col_dist(1), row_n(1), row_k(1), &
2054 row_dist=row_dist, col_dist=col_dist)
2056 row_dist=row_dist, col_dist=col_dist)
2058 row_dist=row_dist, col_dist=col_dist)
2060 CALL create_one_block(x_re,
'rotation_ref_x_re', dist_nk, row_n, col_k)
2061 CALL create_one_block(x_im,
'rotation_ref_x_im', dist_nk, row_n, col_k)
2062 CALL create_one_block(sx_re,
'rotation_ref_sx_re', dist_nk, row_n, col_k)
2063 CALL create_one_block(sx_im,
'rotation_ref_sx_im', dist_nk, row_n, col_k)
2064 CALL create_one_block(c_re,
'rotation_ref_c_re', dist_nk, row_n, col_k)
2065 CALL create_one_block(c_im,
'rotation_ref_c_im', dist_nk, row_n, col_k)
2066 CALL create_one_block(hc_re,
'rotation_ref_hc_re', dist_nk, row_n, col_k)
2067 CALL create_one_block(hc_im,
'rotation_ref_hc_im', dist_nk, row_n, col_k)
2068 CALL create_one_block(g_re,
'rotation_ref_g_re', dist_nk, row_n, col_k)
2069 CALL create_one_block(g_im,
'rotation_ref_g_im', dist_nk, row_n, col_k)
2070 CALL create_one_block(s_re,
'rotation_ref_s_re', dist_nn, row_n, col_n)
2071 CALL create_one_block(s_im,
'rotation_ref_s_im', dist_nn, row_n, col_n)
2072 CALL create_one_block(f_re,
'rotation_ref_f_re', dist_kk, row_k, col_k)
2073 CALL create_one_block(f_im,
'rotation_ref_f_im', dist_kk, row_k, col_k)
2074 DO i = 1,
SIZE(sym_buffer)
2075 CALL create_one_block(sym_buffer(i),
'rotation_ref_sym', dist_kk, row_k, col_k)
2077 DO i = 1,
SIZE(nonsym_buffer)
2078 CALL create_one_block(nonsym_buffer(i),
'rotation_ref_nonsym', dist_kk, row_k, col_k)
2080 DO i = 1,
SIZE(nk_buffer)
2081 CALL create_one_block(nk_buffer(i),
'rotation_ref_nk', dist_nk, row_n, col_k)
2083 DO i = 1,
SIZE(rot_matrix)
2084 CALL create_one_block(rot_matrix(i),
'rotation_ref_rot', dist_kk, row_k, col_k)
2087 CALL put_complex_pair(x_re, x_im, x_dense)
2088 CALL put_complex_pair(s_re, s_im, overlap)
2089 CALL put_complex_pair(rot_matrix(3), rot_matrix(4), generator)
2091 rotation_env%has_complex_kpoint_state = .true.
2092 rotation_env%settings%do_rotation = .true.
2093 rotation_env%settings%eps_irac_filter_matrix = 0.0_dp
2094 rotation_env%settings%ot_method =
'LBFG'
2095 rotation_env%para_env => local_para_env
2096 rotation_env%blacs_env => blacs_env
2097 rotation_env%matrix_x => x_re
2098 rotation_env%matrix_x_im => x_im
2099 rotation_env%matrix_sx => sx_re
2100 rotation_env%matrix_sx_im => sx_im
2101 rotation_env%matrix_gx => g_re
2102 rotation_env%matrix_gx_im => g_im
2103 rotation_env%matrix_ref_inv_sqrt => f_re
2104 rotation_env%matrix_ref_inv_sqrt_im => f_im
2105 rotation_env%buf1_k_k_sym => sym_buffer(1)
2106 rotation_env%buf2_k_k_sym => sym_buffer(2)
2107 rotation_env%buf3_k_k_sym => sym_buffer(3)
2108 rotation_env%buf4_k_k_sym => sym_buffer(4)
2109 rotation_env%buf1_k_k_nosym => nonsym_buffer(1)
2110 rotation_env%buf2_k_k_nosym => nonsym_buffer(2)
2111 rotation_env%buf3_k_k_nosym => nonsym_buffer(3)
2112 rotation_env%buf1_n_k => nk_buffer(1)
2113 rotation_env%buf1_n_k_dp => nk_buffer(2)
2114 rotation_env%rot_mat_u => rot_matrix(1)
2115 rotation_env%rot_mat_u_im => rot_matrix(2)
2116 rotation_env%rot_mat_x => rot_matrix(3)
2117 rotation_env%rot_mat_x_im => rot_matrix(4)
2118 rotation_env%rot_mat_dedu => rot_matrix(5)
2119 rotation_env%rot_mat_dedu_im => rot_matrix(6)
2120 rotation_env%rot_mat_gx => rot_matrix(7)
2121 rotation_env%rot_mat_gx_im => rot_matrix(8)
2122 rotation_env%rot_mat_evec_re => rot_matrix(9)
2123 rotation_env%rot_mat_evec_im => rot_matrix(10)
2124 rotation_env%rot_mat_evals => rotation_evals
2131 CALL get_complex_pair(c_re, c_im, c_dense)
2132 error_c = maxval(abs(c_dense - c_reference))
2134 hc_dense = 2.0_dp*matmul(hamiltonian, c_dense)
2136 hc_dense(:, j) = occupation(j)*hc_dense(:, j)
2138 CALL put_complex_pair(hc_re, hc_im, hc_dense)
2142 CALL get_complex_pair(g_re, g_im, gradient_x)
2143 CALL get_complex_pair(rot_matrix(7), rot_matrix(8), gradient_a)
2146 fd_ref = (rotated_polar_energy(x_dense + hstep*direction_x, generator, &
2147 hamiltonian, occupation) - &
2148 rotated_polar_energy(x_dense - hstep*direction_x, generator, &
2149 hamiltonian, occupation))/(2.0_dp*hstep)
2150 predicted_ref = real(sum(conjg(gradient_x)*direction_x), kind=
dp)
2151 error_ref = abs(predicted_ref - fd_ref)
2153 fd_rot = (rotated_polar_energy(x_dense, generator + hstep*direction_a, &
2154 hamiltonian, occupation) - &
2155 rotated_polar_energy(x_dense, generator - hstep*direction_a, &
2156 hamiltonian, occupation))/(2.0_dp*hstep)
2157 predicted_rot = 0.5_dp*(sum(real(gradient_a, kind=
dp)*real(direction_a, kind=
dp)) + &
2158 sum(aimag(gradient_a)*aimag(direction_a)))
2159 error_rot = abs(predicted_rot - fd_rot)
2161 IF (error_c > 5.0e-11_dp .OR. error_ref > 5.0e-8_dp .OR. &
2162 error_rot > 5.0e-8_dp) nfail = nfail + 1
2163 IF (para_env%is_source())
THEN
2164 WRITE (io_unit,
'(A,1X,ES13.6)')
'complex finite REF rotation orbital error', error_c
2165 WRITE (io_unit,
'(A,3(1X,ES13.6))')
'complex finite REF slope fd/predicted/error', &
2166 fd_ref, predicted_ref, error_ref
2167 WRITE (io_unit,
'(A,3(1X,ES13.6))')
'complex finite rotation slope fd/predicted/error', &
2168 fd_rot, predicted_rot, error_rot
2171 DO i = 1,
SIZE(rot_matrix)
2174 DO i = 1,
SIZE(nk_buffer)
2177 DO i = 1,
SIZE(nonsym_buffer)
2180 DO i = 1,
SIZE(sym_buffer)
2200 DEALLOCATE (pgrid, row_dist, col_dist, row_n, row_k, col_n, col_k)
2204 END SUBROUTINE test_complex_ref_rotation
2211 SUBROUTINE test_complex_rotation_frechet(para_env, nfail)
2213 INTEGER,
INTENT(INOUT) :: nfail
2215 INTEGER,
PARAMETER :: m = 3
2217 COMPLEX(KIND=dp),
DIMENSION(m, m) :: direction, fd, generator, predicted
2219 REAL(KIND=
dp) :: error, hstep
2220 REAL(KIND=
dp),
DIMENSION(m) :: evals
2222 evals = [-0.7_dp, 0.2000003_dp, 1.1_dp]
2223 generator(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2225 generator(i, i) = cmplx(0.0_dp, -evals(i), kind=
dp)
2227 direction(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2228 direction(1, 2) = cmplx(0.17_dp, -0.09_dp, kind=
dp)
2229 direction(2, 1) = -conjg(direction(1, 2))
2230 direction(1, 3) = cmplx(-0.06_dp, 0.13_dp, kind=
dp)
2231 direction(3, 1) = -conjg(direction(1, 3))
2232 direction(2, 3) = cmplx(0.11_dp, 0.04_dp, kind=
dp)
2233 direction(3, 2) = -conjg(direction(2, 3))
2234 direction(1, 1) = cmplx(0.0_dp, 0.08_dp, kind=
dp)
2235 direction(2, 2) = cmplx(0.0_dp, -0.03_dp, kind=
dp)
2236 direction(3, 3) = cmplx(0.0_dp, 0.05_dp, kind=
dp)
2245 fd = (dense_antihermitian_exp(generator + hstep*direction) - &
2246 dense_antihermitian_exp(generator - hstep*direction))/(2.0_dp*hstep)
2247 error = maxval(abs(fd - predicted))
2248 IF (error > 5.0e-9_dp) nfail = nfail + 1
2249 IF (para_env%is_source())
THEN
2250 WRITE (io_unit,
'(A,1X,ES13.6)')
'complex rotation Frechet finite-difference error', error
2253 END SUBROUTINE test_complex_rotation_frechet
2260 SUBROUTINE test_sparse_frechet_patterns(para_env, nfail)
2262 INTEGER,
INTENT(INOUT) :: nfail
2264 COMPLEX(KIND=dp) :: expected, value
2265 INTEGER,
DIMENSION(:),
POINTER :: col_dist, col_size, row_dist, row_size
2266 INTEGER,
DIMENSION(:, :),
POINTER :: pgrid
2268 REAL(kind=
dp) :: error
2269 REAL(kind=
dp),
DIMENSION(2) :: evals
2270 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: block
2272 TYPE(
dbcsr_type) :: inner_im, inner_re, outer_im, outer_re
2274 ALLOCATE (pgrid(0:0, 0:0), row_dist(2), col_dist(2), row_size(2), col_size(2))
2281 row_dist=row_dist, col_dist=col_dist)
2282 CALL dbcsr_create(inner_re,
'frechet_sparse_re', dist, dbcsr_type_no_symmetry, row_size, col_size)
2285 CALL dbcsr_create(inner_im,
'frechet_sparse_im', dist, dbcsr_type_no_symmetry, row_size, col_size)
2291 evals = [-0.4_dp, 0.9_dp]
2295 value = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2297 IF (found)
value =
value + cmplx(block(1, 1), 0.0_dp, kind=
dp)
2299 IF (found)
value =
value + cmplx(0.0_dp, block(1, 1), kind=
dp)
2300 error = max(error, abs(
value - expected))
2303 value = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2305 IF (found)
value =
value + cmplx(block(1, 1), 0.0_dp, kind=
dp)
2307 IF (found)
value =
value + cmplx(0.0_dp, block(1, 1), kind=
dp)
2308 error = max(error, abs(
value - expected))
2309 IF (error > 5.0e-14_dp) nfail = nfail + 1
2310 IF (para_env%is_source())
THEN
2311 WRITE (io_unit,
'(A,1X,ES13.6)')
'sparse complex Frechet block-union error', error
2319 DEALLOCATE (pgrid, row_dist, col_dist, row_size, col_size)
2321 END SUBROUTINE test_sparse_frechet_patterns
2332 SUBROUTINE test_complex_strict_derivative(dist_nk, dist_kk, row_n, row_k, col_k, para_env, nfail)
2334 INTEGER,
DIMENSION(:),
INTENT(INOUT),
POINTER :: row_n, row_k, col_k
2336 INTEGER,
INTENT(INOUT) :: nfail
2338 CHARACTER(LEN=32) :: name
2339 COMPLEX(KIND=dp),
DIMENSION(k, k) :: direction_a, generator, gradient_a, &
2340 inverse_sqrt, rotation
2341 COMPLEX(KIND=dp),
DIMENSION(n, k) :: c0, direction, gradient, hc, orbitals, &
2342 orbitals_base, sc0, sx, x
2343 COMPLEX(KIND=dp),
DIMENSION(n, n) :: hamiltonian, overlap
2346 REAL(KIND=
dp) :: error, error_rot, fd_slope, &
2347 fd_slope_rot, hstep, ortho_error, &
2349 REAL(KIND=
dp),
DIMENSION(:, :),
POINTER :: block
2350 REAL(KIND=
dp),
DIMENSION(k) :: occupation
2351 REAL(KIND=
dp),
DIMENSION(k),
TARGET :: rotation_evals
2353 TYPE(
dbcsr_type),
DIMENSION(10),
TARGET :: rot_matrix
2354 TYPE(
dbcsr_type),
DIMENSION(15),
TARGET :: nk
2355 TYPE(
dbcsr_type),
DIMENSION(25),
TARGET :: kk
2356 TYPE(
dbcsr_type),
POINTER :: hc_im_p, hc_re_p, sx_im_p, sx_re_p, &
2361 NULLIFY (blacs_env, hc_im_p, hc_re_p, strict_para_env, x_im_p, x_re_p, sx_im_p, sx_re_p)
2362 ALLOCATE (strict_para_env)
2366 WRITE (name,
'(A,I0)')
'complex_strict_nk_', i
2367 CALL create_one_block(nk(i), trim(name), dist_nk, row_n, col_k)
2370 WRITE (name,
'(A,I0)')
'complex_strict_kk_', i
2371 CALL create_one_block(kk(i), trim(name), dist_kk, row_k, col_k)
2373 DO i = 1,
SIZE(rot_matrix)
2374 WRITE (name,
'(A,I0)')
'complex_strict_rot_', i
2375 CALL create_one_block(rot_matrix(i), trim(name), dist_kk, row_k, col_k)
2378 overlap(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2379 overlap(1, 1) = cmplx(1.0_dp, 0.0_dp, kind=
dp)
2380 overlap(2, 2) = cmplx(1.2_dp, 0.0_dp, kind=
dp)
2381 overlap(3, 3) = cmplx(1.4_dp, 0.0_dp, kind=
dp)
2382 overlap(1, 2) = cmplx(0.06_dp, 0.03_dp, kind=
dp)
2383 overlap(2, 1) = conjg(overlap(1, 2))
2384 overlap(1, 3) = cmplx(-0.04_dp, 0.02_dp, kind=
dp)
2385 overlap(3, 1) = conjg(overlap(1, 3))
2386 overlap(2, 3) = cmplx(0.05_dp, -0.01_dp, kind=
dp)
2387 overlap(3, 2) = conjg(overlap(2, 3))
2389 c0(:, 1) = [cmplx(1.0_dp, 0.10_dp, kind=
dp), cmplx(0.12_dp, -0.08_dp, kind=
dp), &
2390 cmplx(-0.07_dp, 0.04_dp, kind=
dp)]
2391 c0(:, 2) = [cmplx(0.09_dp, 0.05_dp, kind=
dp), cmplx(0.85_dp, -0.12_dp, kind=
dp), &
2392 cmplx(0.11_dp, 0.06_dp, kind=
dp)]
2393 CALL dense_inverse_sqrt(matmul(conjg(transpose(c0)), matmul(overlap, c0)), inverse_sqrt)
2394 c0 = matmul(c0, inverse_sqrt)
2396 x(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2397 x(3, 1) = cmplx(0.23_dp, 0.17_dp, kind=
dp)
2398 x(3, 2) = cmplx(-0.14_dp, 0.21_dp, kind=
dp)
2399 x = x - matmul(c0, matmul(conjg(transpose(c0)), matmul(overlap, x)))
2400 direction(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2401 direction(3, 1) = cmplx(0.11_dp, -0.09_dp, kind=
dp)
2402 direction(3, 2) = cmplx(0.07_dp, 0.13_dp, kind=
dp)
2403 direction = direction - matmul(c0, matmul(conjg(transpose(c0)), matmul(overlap, direction)))
2405 hamiltonian(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2406 hamiltonian(1, 1) = cmplx(-0.70_dp, 0.0_dp, kind=
dp)
2407 hamiltonian(2, 2) = cmplx(-0.20_dp, 0.0_dp, kind=
dp)
2408 hamiltonian(3, 3) = cmplx(0.90_dp, 0.0_dp, kind=
dp)
2409 hamiltonian(1, 2) = cmplx(0.08_dp, 0.04_dp, kind=
dp)
2410 hamiltonian(2, 1) = conjg(hamiltonian(1, 2))
2411 hamiltonian(1, 3) = cmplx(-0.12_dp, 0.07_dp, kind=
dp)
2412 hamiltonian(3, 1) = conjg(hamiltonian(1, 3))
2413 hamiltonian(2, 3) = cmplx(0.05_dp, -0.09_dp, kind=
dp)
2414 hamiltonian(3, 2) = conjg(hamiltonian(2, 3))
2416 generator(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2417 generator(1, 1) = cmplx(0.0_dp, 0.16_dp, kind=
dp)
2418 generator(2, 2) = cmplx(0.0_dp, -0.09_dp, kind=
dp)
2419 generator(1, 2) = cmplx(0.18_dp, -0.07_dp, kind=
dp)
2420 generator(2, 1) = -conjg(generator(1, 2))
2421 direction_a(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2422 direction_a(1, 1) = cmplx(0.0_dp, -0.05_dp, kind=
dp)
2423 direction_a(2, 2) = cmplx(0.0_dp, 0.04_dp, kind=
dp)
2424 direction_a(1, 2) = cmplx(-0.08_dp, 0.06_dp, kind=
dp)
2425 direction_a(2, 1) = -conjg(direction_a(1, 2))
2426 occupation = [1.0_dp, 0.34_dp]
2428 CALL strict_orbitals(c0, x, overlap, orbitals_base)
2429 rotation = dense_antihermitian_exp(generator)
2430 orbitals = matmul(orbitals_base, rotation)
2431 hc = 2.0_dp*matmul(hamiltonian, orbitals)
2433 hc(:, i) = occupation(i)*hc(:, i)
2435 sx = matmul(overlap, x)
2436 sc0 = matmul(overlap, c0)
2437 CALL put_complex_pair(nk(1), nk(2), x)
2438 CALL put_complex_pair(nk(3), nk(4), sx)
2439 CALL put_complex_pair(nk(5), nk(6), hc)
2440 CALL put_complex_pair(nk(9), nk(10), c0)
2441 CALL put_complex_pair(nk(11), nk(12), sc0)
2442 CALL put_complex_pair(rot_matrix(3), rot_matrix(4), generator)
2444 strict_env%has_complex_kpoint_state = .true.
2445 strict_env%settings%ot_algorithm =
'TOD'
2446 strict_env%settings%do_rotation = .true.
2447 strict_env%para_env => strict_para_env
2448 strict_env%blacs_env => blacs_env
2449 strict_env%matrix_x => nk(1)
2450 strict_env%matrix_x_im => nk(2)
2451 strict_env%matrix_sx => nk(3)
2452 strict_env%matrix_sx_im => nk(4)
2453 strict_env%matrix_gx => nk(7)
2454 strict_env%matrix_gx_im => nk(8)
2455 strict_env%matrix_c0 => nk(9)
2456 strict_env%matrix_c0_im => nk(10)
2457 strict_env%matrix_sc0 => nk(11)
2458 strict_env%matrix_sc0_im => nk(12)
2459 strict_env%matrix_buf_nk => nk(13)
2460 strict_env%matrix_buf_nk_im => nk(14)
2461 strict_env%matrix_tmp_nk => nk(15)
2462 strict_env%matrix_p => kk(1)
2463 strict_env%matrix_p_im => kk(2)
2464 strict_env%matrix_r => kk(3)
2465 strict_env%matrix_r_im => kk(4)
2466 strict_env%matrix_sinp => kk(5)
2467 strict_env%matrix_sinp_im => kk(6)
2468 strict_env%matrix_cosp => kk(7)
2469 strict_env%matrix_cosp_im => kk(8)
2470 strict_env%matrix_sinp_b => kk(9)
2471 strict_env%matrix_cosp_b => kk(10)
2472 strict_env%matrix_buf1 => kk(11)
2473 strict_env%matrix_buf1_im => kk(12)
2474 strict_env%matrix_buf2 => kk(13)
2475 strict_env%matrix_buf2_im => kk(14)
2476 strict_env%matrix_buf3 => kk(15)
2477 strict_env%matrix_buf3_im => kk(16)
2478 strict_env%matrix_buf4 => kk(17)
2479 strict_env%matrix_buf4_im => kk(18)
2480 strict_env%matrix_os => kk(19)
2481 strict_env%matrix_os_im => kk(20)
2482 strict_env%matrix_buf1_ortho => kk(21)
2483 strict_env%matrix_buf1_ortho_im => kk(22)
2484 strict_env%matrix_buf2_ortho => kk(23)
2485 strict_env%matrix_buf2_ortho_im => kk(24)
2486 strict_env%matrix_tmp_ortho => kk(25)
2487 strict_env%rot_mat_u => rot_matrix(1)
2488 strict_env%rot_mat_u_im => rot_matrix(2)
2489 strict_env%rot_mat_x => rot_matrix(3)
2490 strict_env%rot_mat_x_im => rot_matrix(4)
2491 strict_env%rot_mat_dedu => rot_matrix(5)
2492 strict_env%rot_mat_dedu_im => rot_matrix(6)
2493 strict_env%rot_mat_gx => rot_matrix(7)
2494 strict_env%rot_mat_gx_im => rot_matrix(8)
2495 strict_env%rot_mat_evec_re => rot_matrix(9)
2496 strict_env%rot_mat_evec_im => rot_matrix(10)
2497 strict_env%rot_mat_evals => rotation_evals
2498 ALLOCATE (strict_env%evals(k), strict_env%dum(k))
2509 gradient(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2511 IF (found) gradient = gradient + cmplx(block, 0.0_dp, kind=
dp)
2513 IF (found) gradient = gradient + cmplx(0.0_dp, block, kind=
dp)
2514 CALL get_complex_pair(rot_matrix(7), rot_matrix(8), gradient_a)
2517 fd_slope = (strict_rotated_energy(c0, x + hstep*direction, generator, overlap, &
2518 hamiltonian, occupation) - &
2519 strict_rotated_energy(c0, x - hstep*direction, generator, overlap, &
2520 hamiltonian, occupation))/(2.0_dp*hstep)
2521 slope = real(sum(conjg(gradient)*direction), kind=
dp)
2522 error = abs(slope - fd_slope)
2523 fd_slope_rot = (strict_rotated_energy(c0, x, generator + hstep*direction_a, overlap, &
2524 hamiltonian, occupation) - &
2525 strict_rotated_energy(c0, x, generator - hstep*direction_a, overlap, &
2526 hamiltonian, occupation))/(2.0_dp*hstep)
2527 slope_rot = 0.5_dp*(sum(real(gradient_a, kind=
dp)*real(direction_a, kind=
dp)) + &
2528 sum(aimag(gradient_a)*aimag(direction_a)))
2529 error_rot = abs(slope_rot - fd_slope_rot)
2530 ortho_error = maxval(abs(matmul(conjg(transpose(orbitals)), matmul(overlap, orbitals)) - &
2531 reshape([cmplx(1.0_dp, 0.0_dp, kind=
dp), &
2532 cmplx(0.0_dp, 0.0_dp, kind=
dp), &
2533 cmplx(0.0_dp, 0.0_dp, kind=
dp), &
2534 cmplx(1.0_dp, 0.0_dp, kind=
dp)], [k, k])))
2535 IF (error > 5.0e-8_dp .OR. error_rot > 5.0e-8_dp .OR. &
2536 ortho_error > 5.0e-13_dp) nfail = nfail + 1
2537 IF (para_env%is_source())
THEN
2538 WRITE (io_unit,
'(A,3(1X,ES13.6))')
'complex finite-STRICT derivative: fd/predicted/error', &
2539 fd_slope, slope, error
2540 WRITE (io_unit,
'(A,3(1X,ES13.6))')
'complex finite-STRICT rotation: fd/predicted/error', &
2541 fd_slope_rot, slope_rot, error_rot
2542 WRITE (io_unit,
'(A,1X,ES13.6)')
'complex finite-STRICT orthonormality error', ortho_error
2545 DEALLOCATE (strict_env%evals, strict_env%dum)
2546 DO i =
SIZE(rot_matrix), 1, -1
2549 DO i =
SIZE(kk), 1, -1
2552 DO i =
SIZE(nk), 1, -1
2558 END SUBROUTINE test_complex_strict_derivative
2564 SUBROUTINE test_complex_preconditioner_gauge(para_env, nfail)
2566 INTEGER,
INTENT(INOUT) :: nfail
2568 COMPLEX(KIND=dp) :: value
2569 COMPLEX(KIND=dp),
DIMENSION(k) :: phases
2570 COMPLEX(KIND=dp),
DIMENSION(n, k) :: c0, c0_phase, c0_rot, gradient, &
2571 gradient_phase, gradient_rot, output, &
2572 output_phase, output_rot
2573 COMPLEX(KIND=dp),
DIMENSION(n, n) :: eigenvectors, full_all_vectors, h, inverse, &
2574 inverse_rot, inverse_s, inverse_single, inverse_t, reference_s, reference_t, s, &
2577 REAL(KIND=
dp) :: covariant_descent, covariant_gauge_error, full_all_descent, &
2578 full_all_gauge_error, full_all_orthogonality_error, full_single_hermitian_error, &
2579 gauge_error, hermitian_error, low_rank_descent, low_rank_gauge_error, s_error, t_error
2580 REAL(KIND=
dp),
DIMENSION(k) :: c0_evals
2581 REAL(KIND=
dp),
DIMENSION(n) :: eigenvalues, eigenvalues_single
2583 TYPE(
cp_cfm_type) :: matrix_c0, matrix_c0_phase, matrix_c0_rot, matrix_gradient, &
2584 matrix_gradient_phase, matrix_gradient_rot, matrix_h, matrix_output, matrix_output_phase, &
2585 matrix_output_rot, matrix_s, matrix_t
2587 TYPE(
preconditioner_type) :: covariant, covariant_rot, full_all, full_all_phase, low_rank, &
2588 low_rank_rot, preconditioner, preconditioner_rot, preconditioner_s, &
2589 preconditioner_single, preconditioner_t
2591 NULLIFY (blacs_env, fmstruct_nk, fmstruct_nn)
2594 nrow_global=n, ncol_global=n)
2596 nrow_global=n, ncol_global=k)
2597 CALL cp_cfm_create(matrix_h, fmstruct_nn, name=
'complex preconditioner H')
2598 CALL cp_cfm_create(matrix_s, fmstruct_nn, name=
'complex preconditioner S')
2599 CALL cp_cfm_create(matrix_t, fmstruct_nn, name=
'complex preconditioner T')
2600 CALL cp_cfm_create(matrix_c0, fmstruct_nk, name=
'complex preconditioner C')
2601 CALL cp_cfm_create(matrix_c0_phase, fmstruct_nk, name=
'complex preconditioner phased C')
2602 CALL cp_cfm_create(matrix_c0_rot, fmstruct_nk, name=
'complex preconditioner C U')
2603 CALL cp_cfm_create(matrix_gradient, fmstruct_nk, name=
'complex preconditioner gradient')
2605 name=
'complex preconditioner phased gradient')
2607 name=
'complex preconditioner rotated gradient')
2608 CALL cp_cfm_create(matrix_output, fmstruct_nk, name=
'complex preconditioner output')
2610 name=
'complex preconditioner phased output')
2612 name=
'complex preconditioner rotated output')
2620 h(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2621 h(1, 1) = cmplx(-0.35_dp, 0.0_dp, kind=
dp)
2622 h(2, 2) = cmplx(0.15_dp, 0.0_dp, kind=
dp)
2623 h(3, 3) = cmplx(0.90_dp, 0.0_dp, kind=
dp)
2624 h(1, 2) = cmplx(0.08_dp, 0.04_dp, kind=
dp)
2625 h(2, 1) = conjg(h(1, 2))
2626 h(1, 3) = cmplx(-0.06_dp, 0.03_dp, kind=
dp)
2627 h(3, 1) = conjg(h(1, 3))
2628 h(2, 3) = cmplx(0.05_dp, -0.07_dp, kind=
dp)
2629 h(3, 2) = conjg(h(2, 3))
2630 s(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2631 s(1, 1) = cmplx(1.0_dp, 0.0_dp, kind=
dp)
2632 s(2, 2) = cmplx(1.0_dp, 0.0_dp, kind=
dp)
2633 s(3, 3) = cmplx(1.4_dp, 0.0_dp, kind=
dp)
2634 s(1, 3) = cmplx(0.08_dp, 0.03_dp, kind=
dp)
2635 s(3, 1) = conjg(s(1, 3))
2636 s(2, 3) = cmplx(-0.04_dp, 0.02_dp, kind=
dp)
2637 s(3, 2) = conjg(s(2, 3))
2640 t(i, i) = t(i, i) + cmplx(1.50_dp, 0.0_dp, kind=
dp)
2642 c0(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2643 c0(1, 1) = cmplx(1.0_dp, 0.0_dp, kind=
dp)
2644 c0(2, 2) = cmplx(1.0_dp, 0.0_dp, kind=
dp)
2645 c0_rot(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2646 c0_rot(1, 1) = cmplx(sqrt(0.5_dp), 0.0_dp, kind=
dp)
2647 c0_rot(1, 2) = cmplx(0.0_dp, sqrt(0.5_dp), kind=
dp)
2648 c0_rot(2, 1) = cmplx(0.0_dp, sqrt(0.5_dp), kind=
dp)
2649 c0_rot(2, 2) = cmplx(sqrt(0.5_dp), 0.0_dp, kind=
dp)
2650 phases = [exp(cmplx(0.0_dp, 0.43_dp, kind=
dp)), &
2651 exp(cmplx(0.0_dp, -0.67_dp, kind=
dp))]
2653 c0_phase(:, j) = phases(j)*c0(:, j)
2655 gradient(:, 1) = [cmplx(0.17_dp, 0.02_dp, kind=
dp), &
2656 cmplx(-0.08_dp, 0.05_dp, kind=
dp), &
2657 cmplx(0.11_dp, -0.04_dp, kind=
dp)]
2658 gradient(:, 2) = [cmplx(-0.03_dp, 0.06_dp, kind=
dp), &
2659 cmplx(0.09_dp, -0.02_dp, kind=
dp), &
2660 cmplx(-0.14_dp, 0.05_dp, kind=
dp)]
2662 gradient_phase(:, j) = phases(j)*gradient(:, j)
2664 gradient_rot = matmul(gradient, c0_rot(1:k, :))
2665 c0_evals = [real(h(1, 1), kind=
dp), real(h(2, 2), kind=
dp)]
2709 inverse(i, j) =
value
2711 inverse_rot(i, j) =
value
2713 inverse_s(i, j) =
value
2715 inverse_single(i, j) =
value
2717 inverse_t(i, j) =
value
2720 gauge_error = maxval(abs(inverse - inverse_rot))
2721 hermitian_error = maxval(abs(inverse - conjg(transpose(inverse))))
2723 full_single_hermitian_error = maxval(abs(inverse_single - conjg(transpose(inverse_single))))
2724 CALL diag_complex(inverse_single, eigenvectors, eigenvalues_single)
2725 CALL dense_hermitian_inverse(s, reference_s)
2726 CALL dense_hermitian_inverse(t + 0.20_dp*s, reference_t)
2727 s_error = maxval(abs(inverse_s - reference_s))
2728 t_error = maxval(abs(inverse_t - reference_t))
2732 output(i, j) =
value
2734 output_phase(i, j) =
value
2740 full_all_vectors(i, j) =
value
2743 full_all_gauge_error = 0.0_dp
2745 full_all_gauge_error = max(full_all_gauge_error, &
2746 maxval(abs(output_phase(:, j) - phases(j)*output(:, j))))
2748 spectral_metric = matmul(conjg(transpose(full_all_vectors)), &
2749 matmul(s, full_all_vectors))
2750 full_all_orthogonality_error = maxval(abs(spectral_metric - &
2751 reshape([cmplx(1.0_dp, 0.0_dp, kind=
dp), &
2752 cmplx(0.0_dp, 0.0_dp, kind=
dp), &
2753 cmplx(0.0_dp, 0.0_dp, kind=
dp), &
2754 cmplx(0.0_dp, 0.0_dp, kind=
dp), &
2755 cmplx(1.0_dp, 0.0_dp, kind=
dp), &
2756 cmplx(0.0_dp, 0.0_dp, kind=
dp), &
2757 cmplx(0.0_dp, 0.0_dp, kind=
dp), &
2758 cmplx(0.0_dp, 0.0_dp, kind=
dp), &
2759 cmplx(1.0_dp, 0.0_dp, kind=
dp)], [n, n])))
2760 full_all_descent = real(sum(conjg(gradient)*output), kind=
dp)
2763 0.08_dp, 1, 1.0_dp, 1.0e-8_dp)
2765 0.08_dp, 1, 1.0_dp, 1.0e-8_dp)
2771 output(i, j) =
value
2773 output_rot(i, j) =
value
2776 low_rank_gauge_error = maxval(abs(output_rot - matmul(output, c0_rot(1:k, :))))
2777 low_rank_descent = real(sum(conjg(gradient)*output), kind=
dp)
2786 output(i, j) =
value
2788 output_rot(i, j) =
value
2791 covariant_gauge_error = maxval(abs(output_rot - matmul(output, c0_rot(1:k, :))))
2792 covariant_descent = real(sum(conjg(gradient)*output), kind=
dp)
2793 IF (gauge_error > 1.0e-11_dp .OR. hermitian_error > 1.0e-12_dp .OR. &
2794 minval(eigenvalues) <= 0.0_dp) nfail = nfail + 1
2795 IF (s_error > 1.0e-11_dp .OR. t_error > 1.0e-11_dp) nfail = nfail + 1
2796 IF (full_single_hermitian_error > 1.0e-12_dp .OR. &
2797 minval(eigenvalues_single) <= 0.0_dp) nfail = nfail + 1
2798 IF (full_all_gauge_error > 1.0e-11_dp .OR. &
2799 full_all_orthogonality_error > 1.0e-11_dp .OR. full_all_descent <= 0.0_dp) nfail = nfail + 1
2800 IF (low_rank_gauge_error > 1.0e-11_dp .OR. low_rank_descent <= 0.0_dp) nfail = nfail + 1
2801 IF (covariant_gauge_error > 1.0e-11_dp .OR. covariant_descent <= 0.0_dp) nfail = nfail + 1
2802 IF (para_env%is_source())
THEN
2803 WRITE (io_unit,
'(A,3(1X,ES13.6))')
'complex FULL_SINGLE gauge/hermitian/min-eigenvalue', &
2804 gauge_error, hermitian_error, minval(eigenvalues)
2805 WRITE (io_unit,
'(A,2(1X,ES13.6))')
'complex S/KINETIC inverse errors', s_error, t_error
2806 WRITE (io_unit,
'(A,2(1X,ES13.6))')
'complex FULL_SINGLE hermitian/min-eigenvalue', &
2807 full_single_hermitian_error, minval(eigenvalues_single)
2808 WRITE (io_unit,
'(A,3(1X,ES13.6))')
'complex FULL_ALL phase/orthogonality/descent', &
2809 full_all_gauge_error, full_all_orthogonality_error, full_all_descent
2810 WRITE (io_unit,
'(A,2(1X,ES13.6))')
'complex FERMI_LOW_RANK covariance/descent', &
2811 low_rank_gauge_error, low_rank_descent
2812 WRITE (io_unit,
'(A,2(1X,ES13.6))')
'complex FULL_ALL_COVARIANT covariance/descent', &
2813 covariant_gauge_error, covariant_descent
2843 END SUBROUTINE test_complex_preconditioner_gauge
2850 SUBROUTINE test_complex_occupation_block_preconditioner(para_env, nfail)
2852 INTEGER,
INTENT(INOUT) :: nfail
2854 INTEGER,
PARAMETER :: nbas = 4, norb = 3
2856 COMPLEX(KIND=dp) :: value
2857 COMPLEX(KIND=dp),
DIMENSION(nbas, nbas) :: hamiltonian, overlap
2858 COMPLEX(KIND=dp),
DIMENSION(nbas, norb) :: coeff, coeff_rot, gradient, &
2859 gradient_rot, output, output_rot
2860 COMPLEX(KIND=dp),
DIMENSION(norb, norb) :: block_rotation, private_rotation
2862 REAL(KIND=
dp) :: covariance_error, cross_block_error, &
2863 descent, shifted_eigenvalue_error
2864 REAL(KIND=
dp),
DIMENSION(norb, 2) :: occupation_signature
2866 TYPE(
cp_cfm_type) :: matrix_c, matrix_c_rot, matrix_gradient, matrix_gradient_rot, matrix_h, &
2867 matrix_output, matrix_output_rot, matrix_s
2871 NULLIFY (blacs_env, fmstruct_nk, fmstruct_nn)
2874 nrow_global=nbas, ncol_global=nbas)
2876 nrow_global=nbas, ncol_global=norb)
2877 CALL cp_cfm_create(matrix_h, fmstruct_nn, name=
'occupation-block H')
2878 CALL cp_cfm_create(matrix_s, fmstruct_nn, name=
'occupation-block S')
2879 CALL cp_cfm_create(matrix_c, fmstruct_nk, name=
'occupation-block C')
2880 CALL cp_cfm_create(matrix_c_rot, fmstruct_nk, name=
'occupation-block C U')
2881 CALL cp_cfm_create(matrix_gradient, fmstruct_nk, name=
'occupation-block gradient')
2883 name=
'occupation-block rotated gradient')
2884 CALL cp_cfm_create(matrix_output, fmstruct_nk, name=
'occupation-block output')
2885 CALL cp_cfm_create(matrix_output_rot, fmstruct_nk, name=
'occupation-block rotated output')
2887 hamiltonian(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2888 hamiltonian(1, 1) = cmplx(-0.42_dp, 0.0_dp, kind=
dp)
2889 hamiltonian(2, 2) = cmplx(-0.18_dp, 0.0_dp, kind=
dp)
2890 hamiltonian(3, 3) = cmplx(0.07_dp, 0.0_dp, kind=
dp)
2891 hamiltonian(4, 4) = cmplx(0.83_dp, 0.0_dp, kind=
dp)
2892 hamiltonian(1, 2) = cmplx(0.09_dp, 0.04_dp, kind=
dp)
2893 hamiltonian(2, 1) = conjg(hamiltonian(1, 2))
2894 hamiltonian(1, 3) = cmplx(-0.06_dp, 0.03_dp, kind=
dp)
2895 hamiltonian(3, 1) = conjg(hamiltonian(1, 3))
2896 hamiltonian(2, 3) = cmplx(0.05_dp, -0.02_dp, kind=
dp)
2897 hamiltonian(3, 2) = conjg(hamiltonian(2, 3))
2898 hamiltonian(1, 4) = cmplx(0.04_dp, -0.03_dp, kind=
dp)
2899 hamiltonian(4, 1) = conjg(hamiltonian(1, 4))
2900 hamiltonian(2, 4) = cmplx(-0.02_dp, 0.05_dp, kind=
dp)
2901 hamiltonian(4, 2) = conjg(hamiltonian(2, 4))
2902 hamiltonian(3, 4) = cmplx(0.07_dp, 0.01_dp, kind=
dp)
2903 hamiltonian(4, 3) = conjg(hamiltonian(3, 4))
2904 overlap(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2906 overlap(i, i) = cmplx(1.0_dp, 0.0_dp, kind=
dp)
2908 coeff(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2910 coeff(i, i) = cmplx(1.0_dp, 0.0_dp, kind=
dp)
2912 block_rotation(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2913 block_rotation(1, 1) = cmplx(sqrt(0.7_dp), 0.0_dp, kind=
dp)
2914 block_rotation(1, 3) = cmplx(0.0_dp, sqrt(0.3_dp), kind=
dp)
2915 block_rotation(2, 2) = exp(cmplx(0.0_dp, 0.37_dp, kind=
dp))
2916 block_rotation(3, 1) = cmplx(0.0_dp, sqrt(0.3_dp), kind=
dp)
2917 block_rotation(3, 3) = cmplx(sqrt(0.7_dp), 0.0_dp, kind=
dp)
2918 coeff_rot = matmul(coeff, block_rotation)
2919 gradient(:, 1) = [cmplx(0.12_dp, 0.03_dp, kind=
dp), &
2920 cmplx(-0.04_dp, 0.07_dp, kind=
dp), &
2921 cmplx(0.08_dp, -0.02_dp, kind=
dp), &
2922 cmplx(-0.05_dp, 0.06_dp, kind=
dp)]
2923 gradient(:, 2) = [cmplx(-0.06_dp, 0.02_dp, kind=
dp), &
2924 cmplx(0.11_dp, -0.05_dp, kind=
dp), &
2925 cmplx(0.03_dp, 0.09_dp, kind=
dp), &
2926 cmplx(0.07_dp, -0.01_dp, kind=
dp)]
2927 gradient(:, 3) = [cmplx(0.04_dp, -0.08_dp, kind=
dp), &
2928 cmplx(-0.02_dp, 0.05_dp, kind=
dp), &
2929 cmplx(0.10_dp, 0.01_dp, kind=
dp), &
2930 cmplx(-0.03_dp, -0.06_dp, kind=
dp)]
2931 gradient_rot = matmul(gradient, block_rotation)
2932 occupation_signature(:, 1) = [1.0_dp, 1.0_dp, 1.0_dp]
2933 occupation_signature(:, 2) = [1.0_dp, 0.0_dp, 1.0_dp]
2953 0.08_dp, occupation_signature)
2955 0.08_dp, occupation_signature)
2961 output(i, j) =
value
2963 output_rot(i, j) =
value
2969 private_rotation(i, j) =
value
2973 covariance_error = maxval(abs(output_rot - matmul(output, block_rotation)))
2974 cross_block_error = max(maxval(abs(private_rotation([1, 3], 3))), &
2975 maxval(abs(private_rotation(2, 1:2))))
2977 descent = real(sum(conjg(gradient)*output), kind=
dp)
2978 IF (covariance_error > 1.0e-11_dp .OR. cross_block_error > 1.0e-12_dp .OR. &
2979 shifted_eigenvalue_error > 1.0_dp .OR. descent <= 0.0_dp) nfail = nfail + 1
2980 IF (para_env%is_source())
THEN
2981 WRITE (io_unit,
'(A,4(1X,ES13.6))') &
2982 'complex occupation-block covariance/cross-block/max-eigenvalue/descent', &
2983 covariance_error, cross_block_error, shifted_eigenvalue_error, descent
3000 END SUBROUTINE test_complex_occupation_block_preconditioner
3006 SUBROUTINE test_preconditioner_support(nfail)
3007 INTEGER,
INTENT(INOUT) :: nfail
3063 END SUBROUTINE test_preconditioner_support
3073 SUBROUTINE create_one_block(matrix, name, dist, row_size, col_size)
3075 CHARACTER(LEN=*),
INTENT(IN) :: name
3077 INTEGER,
DIMENSION(:),
INTENT(INOUT),
POINTER :: row_size, col_size
3079 CALL dbcsr_create(matrix, name, dist, dbcsr_type_no_symmetry, row_size, col_size)
3083 END SUBROUTINE create_one_block
3091 SUBROUTINE put_complex_pair(matrix_re, matrix_im, matrix)
3092 TYPE(
dbcsr_type),
INTENT(INOUT) :: matrix_re, matrix_im
3093 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: matrix
3098 END SUBROUTINE put_complex_pair
3106 SUBROUTINE get_complex_pair(matrix_re, matrix_im, matrix)
3107 TYPE(
dbcsr_type),
INTENT(INOUT) :: matrix_re, matrix_im
3108 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: matrix
3111 REAL(KIND=
dp),
DIMENSION(:, :),
POINTER :: block
3113 matrix(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
3115 IF (found) matrix = matrix + cmplx(block, 0.0_dp, kind=
dp)
3117 IF (found) matrix = matrix + cmplx(0.0_dp, block, kind=
dp)
3119 END SUBROUTINE get_complex_pair
3129 FUNCTION rotated_polar_energy(x, generator, hamiltonian, occupation)
RESULT(energy)
3130 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: x, generator, hamiltonian
3131 REAL(KIND=
dp),
DIMENSION(:),
INTENT(IN) :: occupation
3132 REAL(KIND=
dp) :: energy
3135 DIMENSION(SIZE(x, 1), SIZE(x, 2)) :: orbitals
3137 DIMENSION(SIZE(x, 2), SIZE(x, 2)) :: inverse_sqrt, rotation
3140 CALL dense_inverse_sqrt(matmul(conjg(transpose(x)), x), inverse_sqrt)
3141 rotation = dense_antihermitian_exp(generator)
3142 orbitals = matmul(matmul(x, inverse_sqrt), rotation)
3144 DO i = 1,
SIZE(occupation)
3145 energy = energy + occupation(i)* &
3146 REAL(DOT_PRODUCT(orbitals(:, i), MATMUL(hamiltonian, orbitals(:, i))), KIND=
dp)
3149 END FUNCTION rotated_polar_energy
3156 FUNCTION dense_antihermitian_exp(generator)
RESULT(rotation)
3157 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: generator
3158 COMPLEX(KIND=dp),
DIMENSION(SIZE(generator, 1), &
SIZE(generator, 2)) :: rotation
3160 COMPLEX(KIND=dp),
DIMENSION(SIZE(generator, 1), &
SIZE(generator, 2)) :: hermitian, vectors
3162 REAL(KIND=
dp),
DIMENSION(SIZE(generator, 1)) :: eigenvalues
3164 hermitian = cmplx(0.0_dp, 1.0_dp, kind=
dp)*generator
3166 rotation(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
3167 DO i = 1,
SIZE(eigenvalues)
3168 rotation = rotation + exp(cmplx(0.0_dp, -eigenvalues(i), kind=
dp))* &
3169 matmul(reshape(vectors(:, i), [
SIZE(generator, 1), 1]), &
3170 reshape(conjg(vectors(:, i)), [1,
SIZE(generator, 1)]))
3173 END FUNCTION dense_antihermitian_exp
3180 SUBROUTINE dense_hermitian_inverse(matrix, inverse)
3181 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: matrix
3182 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: inverse
3185 DIMENSION(SIZE(matrix, 1), SIZE(matrix, 2)) :: vectors
3187 REAL(KIND=
dp),
DIMENSION(SIZE(matrix, 1)) :: eigenvalues
3190 inverse(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
3191 DO i = 1,
SIZE(eigenvalues)
3192 inverse = inverse + matmul(reshape(vectors(:, i), [
SIZE(matrix, 1), 1]), &
3193 reshape(conjg(vectors(:, i)), [1,
SIZE(matrix, 1)]))/ &
3197 END SUBROUTINE dense_hermitian_inverse
3204 SUBROUTINE dense_inverse_sqrt(matrix, inverse)
3205 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: matrix
3206 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: inverse
3209 DIMENSION(SIZE(matrix, 1), SIZE(matrix, 2)) :: vectors
3211 REAL(KIND=
dp),
DIMENSION(SIZE(matrix, 1)) :: eigenvalues
3214 inverse(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
3215 DO i = 1,
SIZE(eigenvalues)
3216 inverse = inverse + matmul(reshape(vectors(:, i), [
SIZE(matrix, 1), 1]), &
3217 reshape(conjg(vectors(:, i)), [1,
SIZE(matrix, 1)]))/ &
3218 sqrt(eigenvalues(i))
3221 END SUBROUTINE dense_inverse_sqrt
3229 FUNCTION polar_energy(coordinate, hamiltonian)
RESULT(energy)
3230 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: coordinate, hamiltonian
3231 REAL(KIND=
dp) :: energy
3233 COMPLEX(KIND=dp),
DIMENSION(SIZE(coordinate, 1), &
SIZE(coordinate, 2)) :: orbitals
3234 COMPLEX(KIND=dp),
DIMENSION(SIZE(coordinate, 2), &
SIZE(coordinate, 2)) :: inverse
3236 CALL dense_inverse_sqrt(matmul(conjg(transpose(coordinate)), coordinate), inverse)
3237 orbitals = matmul(coordinate, inverse)
3238 energy = real(sum(conjg(orbitals)*matmul(hamiltonian, orbitals)), kind=
dp)
3240 END FUNCTION polar_energy
3249 SUBROUTINE strict_orbitals(c0, coordinate, overlap, orbitals)
3250 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: c0, coordinate, overlap
3251 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: orbitals
3253 COMPLEX(KIND=dp),
DIMENSION(SIZE(coordinate, 2), &
SIZE(coordinate, 2)) :: cosp, sinp, vectors
3255 REAL(KIND=
dp) :: root
3256 REAL(KIND=
dp),
DIMENSION(SIZE(coordinate, 2)) :: eigenvalues
3258 CALL diag_complex(matmul(conjg(transpose(coordinate)), matmul(overlap, coordinate)), &
3259 vectors, eigenvalues)
3260 cosp(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
3261 sinp(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
3262 DO i = 1,
SIZE(eigenvalues)
3263 root = sqrt(max(0.0_dp, eigenvalues(i)))
3264 cosp = cosp + cos(root)*matmul(reshape(vectors(:, i), [
SIZE(vectors, 1), 1]), &
3265 reshape(conjg(vectors(:, i)), [1,
SIZE(vectors, 1)]))
3266 IF (root < 1.0e-12_dp)
THEN
3267 sinp = sinp + matmul(reshape(vectors(:, i), [
SIZE(vectors, 1), 1]), &
3268 reshape(conjg(vectors(:, i)), [1,
SIZE(vectors, 1)]))
3270 sinp = sinp + sin(root)/root* &
3271 matmul(reshape(vectors(:, i), [
SIZE(vectors, 1), 1]), &
3272 reshape(conjg(vectors(:, i)), [1,
SIZE(vectors, 1)]))
3275 orbitals = matmul(c0, cosp) + matmul(coordinate, sinp)
3277 END SUBROUTINE strict_orbitals
3287 FUNCTION strict_energy(c0, coordinate, overlap, hamiltonian)
RESULT(energy)
3288 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: c0, coordinate, overlap, hamiltonian
3289 REAL(KIND=
dp) :: energy
3291 COMPLEX(KIND=dp),
DIMENSION(SIZE(coordinate, 1), &
SIZE(coordinate, 2)) :: orbitals
3293 CALL strict_orbitals(c0, coordinate, overlap, orbitals)
3294 energy = real(sum(conjg(orbitals)*matmul(hamiltonian, orbitals)), kind=
dp)
3296 END FUNCTION strict_energy
3308 FUNCTION strict_rotated_energy(c0, coordinate, generator, overlap, hamiltonian, &
3309 occupation)
RESULT(energy)
3310 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: c0, coordinate, generator, overlap, &
3312 REAL(KIND=
dp),
DIMENSION(:),
INTENT(IN) :: occupation
3313 REAL(KIND=
dp) :: energy
3315 COMPLEX(KIND=dp),
DIMENSION(SIZE(coordinate, 1), &
SIZE(coordinate, 2)) :: orbitals
3318 CALL strict_orbitals(c0, coordinate, overlap, orbitals)
3319 orbitals = matmul(orbitals, dense_antihermitian_exp(generator))
3321 DO i = 1,
SIZE(occupation)
3322 energy = energy + occupation(i)* &
3323 REAL(DOT_PRODUCT(orbitals(:, i), MATMUL(hamiltonian, orbitals(:, i))), KIND=
dp)
3326 END FUNCTION strict_rotated_energy
collects all references to literature in CP2K as new algorithms / method are included from literature...
subroutine, public add_all_references()
adds references that can later be cited / printed using the key
methods related to the blacs parallel environment
subroutine, public cp_blacs_env_release(blacs_env)
releases the given blacs_env
subroutine, public cp_blacs_env_create(blacs_env, para_env, blacs_grid_layout, blacs_repeatable, row_major, grid_2d)
allocates and initializes a type that represent a blacs context
Represents a complex full matrix distributed on many processors.
subroutine, public cp_cfm_get_element(matrix, irow_global, icol_global, alpha)
Get the matrix element by its global index.
subroutine, public cp_cfm_release(matrix)
Releases a full matrix.
subroutine, public cp_cfm_set_element(matrix, irow_global, icol_global, alpha)
Set the matrix element (irow_global,icol_global) of the full matrix to alpha.
subroutine, public cp_cfm_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
Creates a new full matrix with the given structure.
subroutine, public cp_cfm_set_all(matrix, alpha, beta)
Set all elements of the full matrix to alpha. Besides, set all diagonal matrix elements to beta (if g...
subroutine, public dbcsr_distribution_release(dist)
...
subroutine, public dbcsr_distribution_new(dist, template, group, pgrid, row_dist, col_dist, reuse_arrays)
...
subroutine, public dbcsr_get_block_p(matrix, row, col, block, found, row_size, col_size)
...
subroutine, public dbcsr_reserve_blocks(matrix, rows, cols)
...
subroutine, public dbcsr_finalize(matrix)
...
subroutine, public dbcsr_release(matrix)
...
subroutine, public dbcsr_put_block(matrix, row, col, block, summation)
...
Basic linear algebra operations for full matrices.
subroutine, public cp_complex_fm_gemm(transa, transb, m, n, k, alpha, a_re, a_im, b_re, b_im, beta, c_re, c_im, a_first_col, a_first_row, b_first_col, b_first_row, c_first_col, c_first_row)
Convenience function. Computes the matrix multiplications needed for the multiplication of complex ma...
represent the structure of a full matrix
subroutine, public cp_fm_struct_create(fmstruct, para_env, context, nrow_global, ncol_global, nrow_block, ncol_block, descriptor, first_p_pos, local_leading_dimension, template_fmstruct, square_blocks, force_block)
allocates and initializes a full matrix structure
subroutine, public cp_fm_struct_release(fmstruct)
releases a full matrix structure
represent a full matrix distributed on many processors
subroutine, public cp_fm_set_submatrix(fm, new_values, start_row, start_col, n_rows, n_cols, alpha, beta, transpose)
sets a submatrix of a full matrix fm(start_row:start_row+n_rows,start_col:start_col+n_cols) = alpha*o...
subroutine, public cp_fm_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
creates a new full matrix with the given structure
subroutine, public cp_fm_get_submatrix(fm, target_m, start_row, start_col, n_rows, n_cols, transpose)
gets a submatrix of a full matrix op(target_m)(1:n_rows,1:n_cols) =fm(start_row:start_row+n_rows,...
various routines to log and control the output. The idea is that decisions about where to log should ...
subroutine, public cp_rm_default_logger()
the cousin of cp_add_default_logger, decrements the stack, so that the default logger is what it has ...
subroutine, public cp_logger_release(logger)
releases this logger
subroutine, public cp_logger_create(logger, para_env, print_level, default_global_unit_nr, default_local_unit_nr, global_filename, local_filename, close_global_unit_on_dealloc, iter_info, close_local_unit_on_dealloc, suffix, template_logger)
initializes a logger
subroutine, public cp_add_default_logger(logger)
adds a default logger. MUST be called before logging occours
Defines the basic variable types.
integer, parameter, public dp
Routines needed for kpoint calculation.
subroutine, public kpoint_ot_energy_weighted_density(coeff_re, coeff_im, hc_re, hc_im, occupation, wmat_re, wmat_im)
Build W(k) for noncanonical complex OT orbitals from H(k) C(k). The occupied-space Lagrange multiplie...
Machine interface based on Fortran 2003 and POSIX.
integer, parameter, public default_output_unit
Collection of simple mathematical functions and subroutines.
subroutine, public diag_complex(matrix, eigenvectors, eigenvalues)
Diagonalizes a local complex Hermitian matrix using LAPACK. Based on cp_cfm_heevd.
Interface to the message passing library MPI.
subroutine, public mp_world_init(mp_comm)
initializes the system default communicator
subroutine, public mp_para_env_release(para_env)
releases the para object (to be called when you don't want anymore the shared copy of this object)
type(mp_comm_type), parameter, public mp_comm_self
subroutine, public mp_world_finalize()
Finalize the system default communicator and MPI when CP2K owns MPI.
computes preconditioners, and implements methods to apply them currently used in qs_ot
subroutine, public make_complex_full_single_inverse(preconditioner_env, matrix_c0, matrix_h, matrix_s, energy_gap)
Build a gauge-covariant FULL_SINGLE_INVERSE operator for a complex k-point channel.
subroutine, public make_complex_full_kinetic(preconditioner_env, matrix_t, matrix_s, energy_gap)
Build the inverse complex kinetic-plus-overlap preconditioner.
subroutine, public make_complex_full_s_inverse(preconditioner_env, matrix_s)
Build the inverse complex overlap preconditioner.
subroutine, public make_complex_full_all_covariant(preconditioner_env, matrix_c0, matrix_h, matrix_s, energy_gap, occupation_signature)
Build the gauge-covariant FULL_ALL inverse for a complex k-point channel.
subroutine, public make_complex_full_single(preconditioner_env, matrix_h, matrix_s, energy_homo, energy_gap)
Build the complex spectral FULL_SINGLE preconditioner.
subroutine, public make_complex_fermi_low_rank(preconditioner_env, matrix_c0, matrix_h, matrix_s, energy_gap, max_rank, spectral_window, degeneracy_tolerance)
Build the bounded low-rank spectral inverse for a complex k-point channel.
subroutine, public make_complex_full_all(preconditioner_env, matrix_c0, matrix_h, matrix_s, c0_evals, energy_gap)
Build the state-selective FULL_ALL operator for a complex k-point channel. The occupied/reference sub...
subroutine, public init_preconditioner(preconditioner_env, para_env, blacs_env)
...
subroutine, public destroy_preconditioner(preconditioner_env)
...
computes preconditioners, and implements methods to apply them currently used in qs_ot
pure elemental logical function, public qs_ot_kpoint_preconditioner_supported(preconditioner_type, use_real_wfn)
Return whether a preconditioner is implemented for complex k-point OT.
pure elemental real(kind=dp) function, public qs_ot_kpoint_preconditioner_scale(kpoint_weight)
Scale an inverse k-point Hessian block consistently with its irreducible weight.
pure elemental logical function, public qs_ot_kpoint_preconditioner_solver_supported(preconditioner_type, solver_type, use_real_wfn)
Return whether a solver is implemented for a complex k-point OT preconditioner.
subroutine, public qs_ot_get_derivative_ref_complex(matrix_hc, matrix_hc_im, qs_ot_env, matrix_hc_rotation, matrix_hc_rotation_im)
complex k-point REF derivative dE/dX from H(k)C(k), S(k)C(k), and C(k)
subroutine, public qs_ot_density_secant_hessian(density_step, hamiltonian_step, density_modes, correction, valid, density_norm_sq, response_work)
project a self-adjoint density/Hamiltonian secant onto density-response modes
subroutine, public qs_ot_get_orbitals_ref_complex(matrix_c, matrix_c_im, matrix_s, matrix_s_im, qs_ot_env, qs_ot_env1)
update complex REF k-point orbitals and their S(k)C(k) images
subroutine, public qs_ot_symmetric_abs_solve(matrix, rhs, solution, valid, relative_floor)
apply a positive spectral inverse of a real symmetric response matrix
pure subroutine, public qs_ot_symmetric_sr1_update(matrix, step, response, updated_matrix, valid, relative_tolerance)
add one accepted symmetric response secant to a reference Hessian
subroutine, public qs_ot_fixed_n_projector_frechet(chc, dchc, occupation, kpoint_weight, response_weight, fixed_n_weight_sum, projector_derivative, density_factor)
fixed-N Frechet derivative of a smooth occupation projector
subroutine, public qs_ot_fixed_n_schur_block(rotation_hessian, rayleigh_response, response_weight, rotation_gradient, energy_gradient, schur_block, coupling_vector, schur_rhs)
local block of the fixed-N rotation/energy Schur complement
subroutine, public qs_ot_finite_rotation_response(chc, rotation_generator, occupation, kpoint_weight, rotation_gradient, rotation_hessian, rayleigh_response, difference_step)
finite complex REF rotation Hessian and Rayleigh-energy response
pure subroutine, public qs_ot_fixed_n_energy_gradient(rayleigh_energy, energy_coordinate, response_weight, fixed_n_weight_sum, fixed_n_weighted_residual, gradient)
fixed-N Mermin gradient in auxiliary-energy coordinates
real(kind=dp) function, public qs_ot_antihermitian_spectral_norm(rotation_generator)
spectral norm of a dense anti-Hermitian rotation generator
subroutine, public qs_ot_get_derivative_complex(matrix_hc, matrix_hc_im, qs_ot_env, matrix_hc_rotation, matrix_hc_rotation_im)
finite complex STRICT derivative, projected onto C0^H*S*X=0
subroutine, public qs_ot_projected_response_update(reference_hessian, response_correction, coefficients, valid, projected_gradient, relative_floor)
update a baseline response direction in a small positive physical-response subspace
pure subroutine, public qs_ot_fixed_n_energy_hessian(response_weight, fixed_n_weight_sum, hessian)
dense fixed-N occupation Hessian in auxiliary-energy coordinates
subroutine, public qs_ot_density_secant_orbital_overlaps(overlap_start_current, occupation_start, occupation_current, hamiltonian_step_start, hamiltonian_step_current, density_modes, kpoint_weight, density_norm_sq, response_work, density_overlap, response_overlap, valid)
project a physical density/Hamiltonian secant between moving orbital subspaces
pure complex(kind=dp) function, public qs_ot_complex_exp_frechet_kernel(e1, e2)
Frechet divided-difference kernel for exp(-i*evals).
subroutine, public qs_ot_apply_complex_frechet_dbcsr(evals, inner_deriv_re, inner_deriv_im, outer_deriv_re, outer_deriv_im, adjoint)
apply the complex exponential Frechet kernel to sparse DBCSR Re/Im matrices
subroutine, public qs_ot_density_secant_projected_hessian(density_norm_sq, response_work, density_overlap, response_overlap, correction, valid, secant_mode, secant_position)
form a projected self-adjoint Hxc response from distributed density-space overlaps
subroutine, public qs_ot_rot_mat_derivative(qs_ot_env)
computes the derivative fields with respect to rot_mat_x
subroutine, public qs_ot_fixed_n_multigroup_schur_block(rotation_hessian, rayleigh_response, response_weight, response_group, rotation_gradient, energy_gradient, schur_block, coupling_matrix, schur_rhs)
eliminate spin-resolved auxiliary energies while retaining every fixed-N constraint
subroutine, public qs_ot_density_tangent(rotation_generator, occupation, kpoint_weight, rotation_step, weighted_occupation_step, density_tangent, difference_step)
finite-chart density tangent for coupled complex rotations and fixed-N occupations
subroutine, public qs_ot_generate_rotation(qs_ot_env)
computes the rotation matrix rot_mat_u that is associated to a given rot_mat_x using rot_mat_u=exp(ro...
subroutine, public qs_ot_get_p_complex(matrix_x, matrix_x_im, matrix_sx, matrix_sx_im, qs_ot_env)
compute P=X^H*S*X and the STRICT matrix functions for a complex K-point channel
provides a uniform framework to add references to CP2K cite and output these
subroutine, public remove_all_references()
deallocate the bibliography
subroutine test_split_complex_fm_gemm(para_env, io_unit, nfail)
Check split-complex full-matrix multiplication including adjoints.
program qs_ot_complex_ref_unittest
Regressions for complex k-point OT derivatives and preconditioner guards.
represent a blacs multidimensional parallel environment (for the mpi corrispective see cp_paratypes/m...
Represent a complex full matrix.
keeps the information about the structure of a full matrix
type of a logger, at the moment it contains just a print level starting at which level it should be l...
stores all the informations relevant to an mpi environment