42 apply_preconditioner_complex_batch
54#include "./base/base_uses.f90"
84 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'qs_ot_kp'
86 INTERFACE qs_ot_complex_multiply_local
87 MODULE PROCEDURE qs_ot_complex_multiply_pair_local, qs_ot_complex_multiply_parts_local
91 TYPE qs_ot_local_work_type
92 INTEGER :: n = 0, k = 0, info = 0
93 LOGICAL :: filtered = .false.
94 TYPE(local_gemm_ctxt_type) :: gemm_ctx
95 TYPE(cp_cfm_diag_workspace_type) :: solver
96 COMPLEX(dp),
ALLOCATABLE :: vectors(:, :)
97 REAL(dp),
ALLOCATABLE :: values(:)
98 REAL(dp),
ALLOCATABLE :: hc(:, :, :), x(:, :, :), sx(:, :, :), c0(:, :, :), out(:, :, :), &
99 r(:, :, :), sinp(:, :, :), sc0(:, :, :),
TARGET(:, :, :), os(:, :, :), &
100 buf1(:, :, :), buf2(:, :, :), buf3(:, :, :), buf4(:, :, :), buf_nk(:, :, :), &
101 buf1_ortho(:, :, :), buf2_ortho(:, :, :), sinp_b(:, :), cosp_b(:, :), tmp(:, :), tmp_ortho(:, :)
102 END TYPE qs_ot_local_work_type
112 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: rotation_generator
113 REAL(kind=
dp) :: norm
115 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: eigenvectors
117 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenvalues
119 n =
SIZE(rotation_generator, 1)
120 cpassert(
SIZE(rotation_generator, 2) == n)
123 ALLOCATE (eigenvectors(n, n), eigenvalues(n))
124 CALL diag_complex(cmplx(0.0_dp, 1.0_dp, kind=
dp)*rotation_generator, &
125 eigenvectors, eigenvalues)
126 norm = maxval(abs(eigenvalues))
127 DEALLOCATE (eigenvalues, eigenvectors)
139 weighted_energy_response, local_curvature_sum, fixed_n_curvature_sum)
RESULT(mu_shift)
140 REAL(kind=
dp),
INTENT(IN) :: weighted_energy_response, &
141 local_curvature_sum, &
142 fixed_n_curvature_sum
143 REAL(kind=
dp) :: mu_shift
145 REAL(kind=
dp) :: denominator
147 denominator = fixed_n_curvature_sum
148 IF (abs(denominator) <= epsilon(denominator)) denominator = local_curvature_sum
150 IF (abs(denominator) > epsilon(denominator)) mu_shift = weighted_energy_response/denominator
164 rayleigh_energy, energy_coordinate, response_weight, fixed_n_weight_sum, &
165 fixed_n_weighted_residual, gradient)
166 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: rayleigh_energy, energy_coordinate, &
168 REAL(kind=
dp),
INTENT(IN) :: fixed_n_weight_sum, &
169 fixed_n_weighted_residual
170 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: gradient
172 REAL(kind=
dp) :: fixed_n_mean
174 fixed_n_mean = 0.0_dp
175 IF (abs(fixed_n_weight_sum) > epsilon(fixed_n_weight_sum))
THEN
176 fixed_n_mean = fixed_n_weighted_residual/fixed_n_weight_sum
178 gradient(:) = response_weight(:)* &
179 (fixed_n_mean - (rayleigh_energy(:) - energy_coordinate(:)))
201 rotation_hessian, rayleigh_response, response_weight, response_group, &
202 rotation_gradient, energy_gradient, schur_block, coupling_matrix, schur_rhs)
203 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: rotation_hessian, rayleigh_response
204 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: response_weight
205 INTEGER,
DIMENSION(:),
INTENT(IN) :: response_group
206 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: rotation_gradient, energy_gradient
207 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: schur_block, coupling_matrix
208 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: schur_rhs
210 INTEGER :: group, i, nenergy, ngroups, nrotation
211 REAL(kind=
dp) :: weight
213 nenergy =
SIZE(response_weight)
214 nrotation =
SIZE(rotation_gradient)
215 ngroups =
SIZE(coupling_matrix, 2)
216 cpassert(ngroups > 0)
217 cpassert(all(shape(rotation_hessian) == [nrotation, nrotation]))
218 cpassert(all(shape(rayleigh_response) == [nenergy, nrotation]))
219 cpassert(
SIZE(energy_gradient) == nenergy)
220 cpassert(
SIZE(response_group) == nenergy)
221 cpassert(all(response_group >= 1 .AND. response_group <= ngroups))
222 cpassert(all(shape(schur_block) == [nrotation, nrotation]))
223 cpassert(
SIZE(coupling_matrix, 1) == nrotation)
224 cpassert(
SIZE(schur_rhs) == nrotation)
226 schur_block(:, :) = rotation_hessian(:, :)
227 coupling_matrix(:, :) = 0.0_dp
229 weight = response_weight(i)
230 schur_block(:, :) = schur_block(:, :) - weight* &
231 spread(rayleigh_response(i, :), dim=2, ncopies=nrotation)* &
232 spread(rayleigh_response(i, :), dim=1, ncopies=nrotation)
233 group = response_group(i)
234 coupling_matrix(:, group) = coupling_matrix(:, group) + &
235 weight*rayleigh_response(i, :)
237 schur_block(:, :) = 0.5_dp*(schur_block + transpose(schur_block))
238 schur_rhs(:) = rotation_gradient + &
239 matmul(transpose(rayleigh_response), energy_gradient)
257 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: matrix, rhs
258 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: solution
259 LOGICAL,
INTENT(OUT) :: valid
260 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: relative_floor
262 INTEGER :: i, n, nresolved
263 REAL(kind=
dp) :: eigenvalue_floor, relative_floor_eff, &
265 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenvalues
266 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: eigenvectors, work
269 cpassert(all(shape(matrix) == [n, n]))
270 cpassert(
SIZE(rhs, 1) == n)
271 cpassert(all(shape(solution) == shape(rhs)))
272 valid = all(matrix == matrix) .AND. all(rhs == rhs)
273 IF (.NOT. valid)
THEN
274 solution(:, :) = 0.0_dp
278 relative_floor_eff = sqrt(epsilon(1.0_dp))
279 IF (
PRESENT(relative_floor)) relative_floor_eff = max(relative_floor, relative_floor_eff)
280 ALLOCATE (eigenvalues(n), eigenvectors(n, n), work(n,
SIZE(rhs, 2)))
281 eigenvectors(:, :) = 0.5_dp*(matrix + transpose(matrix))
283 scale = max(1.0_dp, maxval(abs(eigenvalues)))
284 eigenvalue_floor = relative_floor_eff*scale
285 work(:, :) = matmul(transpose(eigenvectors), rhs)
288 IF (abs(eigenvalues(i)) > eigenvalue_floor)
THEN
289 work(i, :) = work(i, :)/abs(eigenvalues(i))
290 nresolved = nresolved + 1
295 solution(:, :) = matmul(eigenvectors, work)
296 valid = nresolved > 0 .AND. all(solution == solution)
297 IF (.NOT. valid) solution(:, :) = 0.0_dp
298 DEALLOCATE (eigenvalues, eigenvectors, work)
321 reference_hessian, response_correction, coefficients, valid, projected_gradient, relative_floor)
323 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: reference_hessian, response_correction
324 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: coefficients
325 LOGICAL,
INTENT(OUT) :: valid
326 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN),
OPTIONAL :: projected_gradient
327 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: relative_floor
330 REAL(kind=
dp) :: eigenvalue_floor, relative_floor_eff, &
332 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenvalues, rhs, work
333 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: eigenvectors
335 n =
SIZE(reference_hessian, 1)
337 cpassert(all(shape(reference_hessian) == [n, n]))
338 cpassert(all(shape(response_correction) == [n, n]))
339 cpassert(
SIZE(coefficients) == n)
340 IF (
PRESENT(projected_gradient))
THEN
341 cpassert(
SIZE(projected_gradient) == n)
343 coefficients(:) = 0.0_dp
344 valid = all(reference_hessian == reference_hessian) .AND. &
345 all(response_correction == response_correction)
346 IF (
PRESENT(projected_gradient))
THEN
347 valid = valid .AND. all(projected_gradient == projected_gradient)
349 IF (.NOT. valid)
RETURN
351 relative_floor_eff = 1.0e-4_dp
352 IF (
PRESENT(relative_floor)) relative_floor_eff = &
353 max(relative_floor, sqrt(epsilon(1.0_dp)))
354 ALLOCATE (eigenvalues(n), eigenvectors(n, n), rhs(n), work(n))
355 eigenvectors(:, :) = 0.5_dp* &
356 (reference_hessian + response_correction + &
357 transpose(reference_hessian + response_correction))
359 scale = max(maxval(abs(eigenvalues)), maxval(abs(reference_hessian)))
360 IF (scale <= tiny(scale))
THEN
362 coefficients(:) = 0.0_dp
363 DEALLOCATE (eigenvalues, eigenvectors, rhs, work)
366 eigenvalue_floor = relative_floor_eff*scale
367 valid = all(eigenvalues > eigenvalue_floor)
369 rhs(:) = reference_hessian(:, 1)
370 IF (
PRESENT(projected_gradient)) rhs(:) = projected_gradient
371 work(:) = matmul(transpose(eigenvectors), rhs)
373 work(i) = work(i)/eigenvalues(i)
375 coefficients(:) = matmul(eigenvectors, work)
376 valid = all(coefficients == coefficients) .AND. &
377 all(abs(coefficients) <= huge(1.0_dp))
379 IF (.NOT. valid) coefficients(:) = 0.0_dp
380 DEALLOCATE (eigenvalues, eigenvectors, rhs, work)
397 density_norm_sq, response_work, density_overlap, response_overlap, correction, valid, &
398 secant_mode, secant_position)
400 REAL(kind=
dp),
INTENT(IN) :: density_norm_sq, response_work
401 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: density_overlap, response_overlap
402 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: correction
403 LOGICAL,
INTENT(OUT) :: valid
404 INTEGER,
INTENT(IN),
OPTIONAL :: secant_mode
405 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: secant_position
407 INTEGER :: i, j, nmode
408 REAL(kind=
dp) :: inverse_density_norm
409 REAL(kind=
dp),
DIMENSION(SIZE(density_overlap)) :: projected_density_overlap, &
410 projected_response_overlap
412 nmode =
SIZE(density_overlap)
413 cpassert(
SIZE(response_overlap) == nmode)
414 cpassert(all(shape(correction) == [nmode, nmode]))
416 correction(:, :) = 0.0_dp
418 IF (nmode <= 0 .OR. density_norm_sq <= tiny(1.0_dp))
RETURN
419 IF (density_norm_sq /= density_norm_sq .OR. response_work /= response_work)
RETURN
420 IF (abs(density_norm_sq) > huge(1.0_dp) .OR. abs(response_work) > huge(1.0_dp))
RETURN
421 IF (any(density_overlap /= density_overlap) .OR. any(response_overlap /= response_overlap))
RETURN
422 IF (any(abs(density_overlap) > huge(1.0_dp)) .OR. &
423 any(abs(response_overlap) > huge(1.0_dp)))
RETURN
424 IF (
PRESENT(secant_mode) .NEQV.
PRESENT(secant_position))
RETURN
426 projected_density_overlap(:) = density_overlap
427 projected_response_overlap(:) = response_overlap
428 IF (
PRESENT(secant_mode))
THEN
429 IF (secant_mode < 1 .OR. secant_mode > nmode)
RETURN
430 IF (secant_position /= secant_position .OR. &
431 abs(secant_position) > huge(1.0_dp) .OR. &
432 abs(secant_position) <= sqrt(epsilon(1.0_dp)))
RETURN
435 projected_density_overlap(secant_mode) = density_norm_sq/secant_position
436 projected_response_overlap(secant_mode) = response_work/secant_position
439 inverse_density_norm = 1.0_dp/density_norm_sq
442 correction(i, j) = inverse_density_norm* &
443 (projected_response_overlap(i)*projected_density_overlap(j) + &
444 projected_density_overlap(i)*projected_response_overlap(j) - &
445 response_work*inverse_density_norm* &
446 projected_density_overlap(i)*projected_density_overlap(j))
449 correction(:, :) = 0.5_dp*(correction + transpose(correction))
450 valid = all(correction == correction) .AND. all(abs(correction) <= huge(1.0_dp))
451 IF (.NOT. valid) correction(:, :) = 0.0_dp
473 rotation_generator, occupation, kpoint_weight, rotation_step, &
474 weighted_occupation_step, density_tangent, difference_step)
476 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: rotation_generator
477 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: occupation
478 REAL(kind=
dp),
INTENT(IN) :: kpoint_weight
479 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: rotation_step, weighted_occupation_step
480 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: density_tangent
481 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: difference_step
483 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: direction, generator_minus, &
484 generator_plus, mode_ref, rotation, rotation_minus, rotation_plus, weighted_rotation
485 INTEGER :: i, j, n, nrotation, r
486 REAL(kind=
dp) :: step, step_scale
488 n =
SIZE(rotation_generator, 1)
489 nrotation = n*(n - 1)
491 cpassert(all(shape(rotation_generator) == [n, n]))
492 cpassert(
SIZE(occupation) == n)
493 cpassert(
SIZE(rotation_step) == nrotation)
494 cpassert(
SIZE(weighted_occupation_step) == n)
495 cpassert(all(shape(density_tangent) == [n, n]))
496 cpassert(kpoint_weight > 0.0_dp)
498 ALLOCATE (direction(n, n), generator_minus(n, n), generator_plus(n, n), &
499 mode_ref(n, n), rotation(n, n), rotation_minus(n, n), &
500 rotation_plus(n, n), weighted_rotation(n, n))
501 direction(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
506 direction(i, j) = cmplx(rotation_step(r), 0.0_dp, kind=
dp)
507 direction(j, i) = -direction(i, j)
509 direction(i, j) = direction(i, j) + &
510 cmplx(0.0_dp, rotation_step(r), kind=
dp)
511 direction(j, i) = direction(j, i) + &
512 cmplx(0.0_dp, rotation_step(r), kind=
dp)
515 cpassert(r == nrotation)
517 step_scale = max(1.0_dp, maxval(abs(direction)))
518 step = 1.0e-5_dp/step_scale
519 IF (
PRESENT(difference_step)) step = difference_step/step_scale
520 cpassert(step > epsilon(step))
521 generator_plus(:, :) = rotation_generator + step*direction
522 generator_minus(:, :) = rotation_generator - step*direction
523 CALL qs_ot_dense_rotation_state(rotation_generator, rotation)
524 CALL qs_ot_dense_rotation_state(generator_plus, rotation_plus)
525 CALL qs_ot_dense_rotation_state(generator_minus, rotation_minus)
527 weighted_rotation(:, :) = rotation_plus
529 weighted_rotation(:, j) = kpoint_weight*occupation(j)*weighted_rotation(:, j)
531 mode_ref(:, :) = matmul(weighted_rotation, conjg(transpose(rotation_plus)))
532 weighted_rotation(:, :) = rotation_minus
534 weighted_rotation(:, j) = kpoint_weight*occupation(j)*weighted_rotation(:, j)
536 mode_ref(:, :) = (mode_ref - &
537 matmul(weighted_rotation, conjg(transpose(rotation_minus))))/(2.0_dp*step)
539 weighted_rotation(:, :) = rotation
541 weighted_rotation(:, j) = weighted_occupation_step(j)*weighted_rotation(:, j)
543 mode_ref(:, :) = mode_ref + matmul(weighted_rotation, conjg(transpose(rotation)))
544 density_tangent(:, :) = matmul(conjg(transpose(rotation)), matmul(mode_ref, rotation))
545 density_tangent(:, :) = 0.5_dp*(density_tangent + conjg(transpose(density_tangent)))
547 DEALLOCATE (direction, generator_minus, generator_plus, mode_ref, rotation, &
548 rotation_minus, rotation_plus, weighted_rotation)
572 overlap_start_current, occupation_start, occupation_current, hamiltonian_step_start, &
573 hamiltonian_step_current, density_modes, kpoint_weight, density_norm_sq, response_work, &
574 density_overlap, response_overlap, valid)
576 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: overlap_start_current
577 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: occupation_start, occupation_current
578 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: hamiltonian_step_start, &
579 hamiltonian_step_current
580 COMPLEX(KIND=dp),
DIMENSION(:, :, :),
INTENT(IN) :: density_modes
581 REAL(kind=
dp),
INTENT(IN) :: kpoint_weight
582 REAL(kind=
dp),
INTENT(OUT) :: density_norm_sq, response_work
583 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: density_overlap, response_overlap
584 LOGICAL,
INTENT(OUT) :: valid
586 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: cross_mode
587 INTEGER :: i, j, mode, n, nmode
588 REAL(kind=
dp) :: cross_density, density_scale
590 n =
SIZE(occupation_start)
591 nmode =
SIZE(density_modes, 3)
593 cpassert(
SIZE(occupation_current) == n)
594 cpassert(all(shape(overlap_start_current) == [n, n]))
595 cpassert(all(shape(hamiltonian_step_start) == [n, n]))
596 cpassert(all(shape(hamiltonian_step_current) == [n, n]))
597 cpassert(
SIZE(density_modes, 1) == n .AND.
SIZE(density_modes, 2) == n)
598 cpassert(
SIZE(density_overlap) == nmode .AND.
SIZE(response_overlap) == nmode)
600 density_norm_sq = 0.0_dp
601 response_work = 0.0_dp
602 density_overlap(:) = 0.0_dp
603 response_overlap(:) = 0.0_dp
605 IF (nmode <= 0 .OR. kpoint_weight <= tiny(1.0_dp))
RETURN
607 cross_density = 0.0_dp
610 cross_density = cross_density + occupation_start(i)*occupation_current(j)* &
611 abs(overlap_start_current(i, j))**2
614 density_norm_sq = kpoint_weight* &
615 (sum(occupation_start**2) + sum(occupation_current**2) - &
616 2.0_dp*cross_density)
617 response_work = 0.0_dp
619 response_work = response_work + kpoint_weight* &
620 (occupation_current(i)*real(hamiltonian_step_current(i, i), kind=
dp) - &
621 occupation_start(i)*real(hamiltonian_step_start(i, i), kind=
dp))
624 ALLOCATE (cross_mode(n, n))
627 CALL gemm_square(overlap_start_current,
"N", density_modes(:, :, mode),
"N", &
628 overlap_start_current,
"C", cross_mode)
630 density_overlap(mode) = density_overlap(mode) + &
631 occupation_current(i)* &
632 REAL(density_modes(i, i, mode), kind=
dp) - &
633 occupation_start(i)*real(cross_mode(i, i), kind=
dp)
635 response_overlap(mode) = &
636 sum(real(hamiltonian_step_current, kind=
dp)* &
637 REAL(density_modes(:, :, mode), kind=
dp) + &
638 aimag(hamiltonian_step_current)*aimag(density_modes(:, :, mode)))
640 DEALLOCATE (cross_mode)
642 density_scale = kpoint_weight* &
643 max(maxval(abs(occupation_start)), maxval(abs(occupation_current)))
644 IF (density_scale <= tiny(1.0_dp))
RETURN
645 IF (density_norm_sq <= 64.0_dp*epsilon(1.0_dp)*density_scale**2)
RETURN
646 valid = density_norm_sq == density_norm_sq .AND. response_work == response_work .AND. &
647 abs(density_norm_sq) <= huge(1.0_dp) .AND. abs(response_work) <= huge(1.0_dp) .AND. &
648 all(density_overlap == density_overlap) .AND. &
649 all(response_overlap == response_overlap) .AND. &
650 all(abs(density_overlap) <= huge(1.0_dp)) .AND. &
651 all(abs(response_overlap) <= huge(1.0_dp))
652 IF (.NOT. valid)
THEN
653 density_norm_sq = 0.0_dp
654 response_work = 0.0_dp
655 density_overlap(:) = 0.0_dp
656 response_overlap(:) = 0.0_dp
678 chc, rotation_generator, occupation, kpoint_weight, rotation_gradient, &
679 rotation_hessian, rayleigh_response, difference_step)
680 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: chc, rotation_generator
681 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: occupation
682 REAL(kind=
dp),
INTENT(IN) :: kpoint_weight
683 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: rotation_gradient
684 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: rotation_hessian, rayleigh_response
685 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: difference_step
687 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: base_hamiltonian, generator_minus, &
688 generator_plus, rotation
689 INTEGER :: i, j, n, nrotation, r, s
690 REAL(kind=
dp) :: step
691 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: occupation_scale, rayleigh, &
692 rayleigh_minus, rayleigh_plus
693 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: gradient_imag, gradient_minus_imag, &
694 gradient_minus_real, gradient_plus_imag, gradient_plus_real, gradient_real
697 nrotation = n*(n - 1)
699 cpassert(all(shape(chc) == [n, n]))
700 cpassert(all(shape(rotation_generator) == [n, n]))
701 cpassert(
SIZE(occupation) == n)
702 cpassert(
SIZE(rotation_gradient) == nrotation)
703 cpassert(all(shape(rotation_hessian) == [nrotation, nrotation]))
704 cpassert(all(shape(rayleigh_response) == [n, nrotation]))
705 cpassert(kpoint_weight > 0.0_dp)
708 IF (
PRESENT(difference_step)) step = difference_step
709 cpassert(step > sqrt(epsilon(step)))
711 ALLOCATE (base_hamiltonian(n, n), generator_minus(n, n), generator_plus(n, n), &
712 rotation(n, n), occupation_scale(n), rayleigh(n), rayleigh_minus(n), &
713 rayleigh_plus(n), gradient_imag(n, n), gradient_minus_imag(n, n), &
714 gradient_minus_real(n, n), gradient_plus_imag(n, n), &
715 gradient_plus_real(n, n), gradient_real(n, n))
717 CALL qs_ot_dense_rotation_state(rotation_generator, rotation)
718 base_hamiltonian(:, :) = matmul(rotation, matmul(chc, conjg(transpose(rotation))))
719 occupation_scale(:) = 2.0_dp*kpoint_weight*occupation(:)
720 CALL qs_ot_dense_rotation_gradient(rotation_generator, base_hamiltonian, occupation_scale, &
721 gradient_real, gradient_imag, rayleigh)
727 rotation_gradient(r) = gradient_real(i, j)
729 rotation_gradient(r) = gradient_imag(i, j)
732 cpassert(r == nrotation)
737 generator_plus(:, :) = rotation_generator(:, :)
738 generator_minus(:, :) = rotation_generator(:, :)
739 generator_plus(i, j) = generator_plus(i, j) + step
740 generator_plus(j, i) = generator_plus(j, i) - step
741 generator_minus(i, j) = generator_minus(i, j) - step
742 generator_minus(j, i) = generator_minus(j, i) + step
744 CALL qs_ot_dense_rotation_gradient(generator_plus, base_hamiltonian, occupation_scale, &
745 gradient_plus_real, gradient_plus_imag, rayleigh_plus)
746 CALL qs_ot_dense_rotation_gradient(generator_minus, base_hamiltonian, occupation_scale, &
747 gradient_minus_real, gradient_minus_imag, rayleigh_minus)
748 CALL qs_ot_pack_rotation_response( &
749 gradient_plus_real, gradient_plus_imag, gradient_minus_real, gradient_minus_imag, &
750 rayleigh_plus, rayleigh_minus, step, rotation_hessian(:, s), &
751 rayleigh_response(:, s))
753 generator_plus(:, :) = rotation_generator(:, :)
754 generator_minus(:, :) = rotation_generator(:, :)
755 generator_plus(i, j) = generator_plus(i, j) + cmplx(0.0_dp, step, kind=
dp)
756 generator_plus(j, i) = generator_plus(j, i) + cmplx(0.0_dp, step, kind=
dp)
757 generator_minus(i, j) = generator_minus(i, j) - cmplx(0.0_dp, step, kind=
dp)
758 generator_minus(j, i) = generator_minus(j, i) - cmplx(0.0_dp, step, kind=
dp)
760 CALL qs_ot_dense_rotation_gradient(generator_plus, base_hamiltonian, occupation_scale, &
761 gradient_plus_real, gradient_plus_imag, rayleigh_plus)
762 CALL qs_ot_dense_rotation_gradient(generator_minus, base_hamiltonian, occupation_scale, &
763 gradient_minus_real, gradient_minus_imag, rayleigh_minus)
764 CALL qs_ot_pack_rotation_response( &
765 gradient_plus_real, gradient_plus_imag, gradient_minus_real, gradient_minus_imag, &
766 rayleigh_plus, rayleigh_minus, step, rotation_hessian(:, s), &
767 rayleigh_response(:, s))
770 cpassert(s == nrotation)
771 rotation_hessian(:, :) = 0.5_dp*(rotation_hessian + transpose(rotation_hessian))
773 DEALLOCATE (base_hamiltonian, generator_minus, generator_plus, rotation, occupation_scale, &
774 rayleigh, rayleigh_minus, rayleigh_plus, gradient_imag, gradient_minus_imag, &
775 gradient_minus_real, gradient_plus_imag, gradient_plus_real, gradient_real)
791 SUBROUTINE qs_ot_pack_rotation_response( &
792 gradient_plus_real, gradient_plus_imag, gradient_minus_real, gradient_minus_imag, &
793 rayleigh_plus, rayleigh_minus, step, hessian_column, rayleigh_column)
794 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: gradient_plus_real, gradient_plus_imag, &
795 gradient_minus_real, &
797 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: rayleigh_plus, rayleigh_minus
798 REAL(kind=
dp),
INTENT(IN) :: step
799 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: hessian_column, rayleigh_column
801 INTEGER :: i, j, n, r
803 n =
SIZE(gradient_plus_real, 1)
804 cpassert(all(shape(gradient_plus_real) == [n, n]))
805 cpassert(all(shape(gradient_plus_imag) == [n, n]))
806 cpassert(all(shape(gradient_minus_real) == [n, n]))
807 cpassert(all(shape(gradient_minus_imag) == [n, n]))
808 cpassert(
SIZE(hessian_column) == n*(n - 1))
809 cpassert(
SIZE(rayleigh_column) == n)
815 hessian_column(r) = &
816 (gradient_plus_real(i, j) - gradient_minus_real(i, j))/(2.0_dp*step)
818 hessian_column(r) = &
819 (gradient_plus_imag(i, j) - gradient_minus_imag(i, j))/(2.0_dp*step)
822 rayleigh_column(:) = (rayleigh_plus(:) - rayleigh_minus(:))/(2.0_dp*step)
824 END SUBROUTINE qs_ot_pack_rotation_response
835 SUBROUTINE qs_ot_dense_rotation_gradient( &
836 rotation_generator, base_hamiltonian, occupation_scale, gradient_real, gradient_imag, rayleigh)
837 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: rotation_generator, base_hamiltonian
838 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: occupation_scale
839 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: gradient_real, gradient_imag
840 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: rayleigh
842 COMPLEX(KIND=dp) :: kernel
843 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: covector, eigenvectors, frechet, inner, &
844 outer, rotation, work
846 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenvalues
848 n =
SIZE(rotation_generator, 1)
849 ALLOCATE (covector(n, n), eigenvectors(n, n), frechet(n, n), inner(n, n), &
850 outer(n, n), rotation(n, n), work(n, n), eigenvalues(n))
851 CALL qs_ot_dense_rotation_state(rotation_generator, rotation, &
852 eigenvectors=eigenvectors, eigenvalues=eigenvalues)
854 work(:, :) = matmul(base_hamiltonian, rotation)
855 covector(:, :) = work(:, :)
857 covector(:, j) = occupation_scale(j)*covector(:, j)
860 work(:, :) = matmul(conjg(transpose(rotation)), &
861 matmul(base_hamiltonian, rotation))
863 rayleigh(i) = real(work(i, i), kind=
dp)
866 inner(:, :) = matmul(conjg(transpose(eigenvectors)), &
867 matmul(covector, eigenvectors))
871 outer(i, j) = inner(i, j)*kernel
874 frechet(:, :) = matmul(eigenvectors, &
875 matmul(outer, conjg(transpose(eigenvectors))))
876 gradient_real(:, :) = real(frechet, kind=
dp) - transpose(real(frechet, kind=
dp))
877 gradient_imag(:, :) = aimag(frechet) + transpose(aimag(frechet))
879 DEALLOCATE (covector, eigenvectors, frechet, inner, outer, rotation, work, eigenvalues)
881 END SUBROUTINE qs_ot_dense_rotation_gradient
890 SUBROUTINE qs_ot_dense_rotation_state(rotation_generator, rotation, eigenvectors, eigenvalues)
891 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: rotation_generator
892 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: rotation
893 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT), &
894 OPTIONAL :: eigenvectors
895 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT),
OPTIONAL :: eigenvalues
897 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: vectors, weighted_vectors
899 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: values
901 n =
SIZE(rotation_generator, 1)
902 ALLOCATE (vectors(n, n), weighted_vectors(n, n), values(n))
903 CALL diag_complex(cmplx(0.0_dp, 1.0_dp, kind=
dp)*rotation_generator, &
905 weighted_vectors(:, :) = vectors(:, :)
907 weighted_vectors(:, j) = exp(cmplx(0.0_dp, -values(j), kind=
dp))* &
908 weighted_vectors(:, j)
910 rotation(:, :) = matmul(weighted_vectors, conjg(transpose(vectors)))
911 IF (
PRESENT(eigenvectors)) eigenvectors(:, :) = vectors(:, :)
912 IF (
PRESENT(eigenvalues)) eigenvalues(:) = values(:)
913 DEALLOCATE (vectors, weighted_vectors, values)
915 END SUBROUTINE qs_ot_dense_rotation_state
924 REAL(kind=
dp),
INTENT(IN) :: e1, e2
925 COMPLEX(KIND=dp) :: kernel
927 COMPLEX(KIND=dp) :: l1, l2, x
930 l1 = (0.0_dp, -1.0_dp)*e1
931 l2 = (0.0_dp, -1.0_dp)*e2
932 IF (abs(l1 - l2) > 0.5_dp)
THEN
933 kernel = (exp(l1) - exp(l2))/(l1 - l2)
939 x = x*(l1 - l2)/real(i + 1, kind=
dp)
941 kernel = kernel*exp(l2)
956 outer_deriv_re, outer_deriv_im, adjoint)
957 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: evals
958 TYPE(
dbcsr_type) :: inner_deriv_re, inner_deriv_im, &
959 outer_deriv_re, outer_deriv_im
960 LOGICAL,
INTENT(IN),
OPTIONAL :: adjoint
962 COMPLEX(KIND=dp) :: cval_in, kernel
963 INTEGER :: col, i, j, max_blocks, nblocks, row
964 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: cols, rows
965 INTEGER,
DIMENSION(:),
POINTER :: col_blk_offset, col_blk_size, &
966 row_blk_offset, row_blk_size
967 LOGICAL :: found_im, found_out_im, found_out_re, &
968 found_re, use_adjoint
969 REAL(
dp),
DIMENSION(:, :),
POINTER :: block_in_im, block_in_re, block_out_im, &
971 REAL(kind=
dp) :: e1, e2, im_part, re_part
975 use_adjoint = .false.
976 IF (
PRESENT(adjoint)) use_adjoint = adjoint
984 max_blocks = max_blocks + 1
990 max_blocks = max_blocks + 1
993 ALLOCATE (rows(max(max_blocks, 1)), cols(max(max_blocks, 1)))
999 CALL append_union_block(row, col)
1005 CALL append_union_block(row, col)
1009 CALL dbcsr_get_info(inner_deriv_re, distribution=dist, row_blk_size=row_blk_size, &
1010 col_blk_size=col_blk_size)
1011 CALL dbcsr_create(outer_deriv_re,
"outer_deriv_re", dist, dbcsr_type_no_symmetry, &
1012 row_blk_size, col_blk_size)
1013 CALL dbcsr_create(outer_deriv_im,
"outer_deriv_im", dist, dbcsr_type_no_symmetry, &
1014 row_blk_size, col_blk_size)
1015 IF (nblocks > 0)
THEN
1024 CALL dbcsr_get_info(outer_deriv_re, row_blk_offset=row_blk_offset, &
1025 col_blk_offset=col_blk_offset)
1033 cpassert(found_out_re .AND. found_out_im)
1035 DO i = 1,
SIZE(block_out_re, 1)
1036 DO j = 1,
SIZE(block_out_re, 2)
1037 e1 = evals(row_blk_offset(row) + i - 1)
1038 e2 = evals(col_blk_offset(col) + j - 1)
1041 IF (found_re) re_part = block_in_re(i, j)
1042 IF (found_im) im_part = block_in_im(i, j)
1043 cval_in = cmplx(re_part, im_part,
dp)
1045 IF (use_adjoint) kernel = conjg(kernel)
1046 cval_in = cval_in*kernel
1047 block_out_re(i, j) = real(cval_in, kind=
dp)
1048 block_out_im(i, j) = aimag(cval_in)
1053 DEALLOCATE (rows, cols)
1062 SUBROUTINE append_union_block(row_new, col_new)
1063 INTEGER,
INTENT(IN) :: row_new, col_new
1067 DO iblock = 1, nblocks
1068 IF (rows(iblock) == row_new .AND. cols(iblock) == col_new)
RETURN
1070 nblocks = nblocks + 1
1071 rows(nblocks) = row_new
1072 cols(nblocks) = col_new
1073 END SUBROUTINE append_union_block
1087 qs_ot_env, qs_ot_env1)
1089 TYPE(
dbcsr_type),
POINTER :: matrix_c, matrix_c_im, matrix_s, &
1094 CHARACTER(len=*),
PARAMETER :: routinen =
'qs_ot_get_orbitals_ref_complex'
1096 INTEGER :: handle, i, k, n
1098 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenvalues, inverse_sqrt
1099 TYPE(
dbcsr_type) :: rotated_im, rotated_re, rotation_tmp
1100 TYPE(
dbcsr_type),
POINTER :: c_im, c_re, f_im, f_re, p_im, p_re, &
1101 sc_im, sc_re, tmp_kk, tmp_nk, v_im, &
1104 CALL timeset(routinen, handle)
1106 cpassert(qs_ot_env%has_complex_kpoint_state)
1107 cpassert(
ASSOCIATED(matrix_s))
1108 cpassert(
ASSOCIATED(matrix_s_im))
1110 c_re => qs_ot_env%matrix_x
1111 c_im => qs_ot_env%matrix_x_im
1112 f_re => qs_ot_env%matrix_ref_inv_sqrt
1113 f_im => qs_ot_env%matrix_ref_inv_sqrt_im
1114 sc_re => qs_ot_env%matrix_sx
1115 sc_im => qs_ot_env%matrix_sx_im
1116 p_re => qs_ot_env%buf1_k_k_sym
1117 p_im => qs_ot_env%buf2_k_k_sym
1118 v_re => qs_ot_env%buf3_k_k_sym
1119 v_im => qs_ot_env%buf4_k_k_sym
1120 w_re => qs_ot_env%buf1_k_k_nosym
1121 w_im => qs_ot_env%buf2_k_k_nosym
1122 tmp_kk => qs_ot_env%buf3_k_k_nosym
1123 tmp_nk => qs_ot_env%buf1_n_k
1126 IF (
PRESENT(qs_ot_env1))
THEN
1137 CALL dbcsr_multiply(
'T',
'N', 1.0_dp, c_im, sc_im, 0.0_dp, tmp_kk)
1138 CALL dbcsr_add(p_re, tmp_kk, alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
1141 CALL dbcsr_multiply(
'T',
'N', 1.0_dp, c_im, sc_re, 0.0_dp, tmp_kk)
1142 CALL dbcsr_add(p_im, tmp_kk, alpha_scalar=1.0_dp, beta_scalar=-1.0_dp)
1144 ALLOCATE (eigenvalues(k), inverse_sqrt(k))
1146 eigenvectors_re=v_re, eigenvectors_im=v_im, &
1147 eigenvalues=eigenvalues, para_env=qs_ot_env%para_env, &
1148 blacs_env=qs_ot_env%blacs_env)
1150 IF (eigenvalues(i) <= epsilon(1.0_dp))
THEN
1151 cpabort(
"Complex REF overlap is not positive definite")
1153 inverse_sqrt(i) = 1.0_dp/sqrt(eigenvalues(i))
1163 CALL dbcsr_multiply(
'N',
'T', 1.0_dp, w_im, v_im, 0.0_dp, tmp_kk)
1164 CALL dbcsr_add(p_re, tmp_kk, alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
1167 CALL dbcsr_multiply(
'N',
'T', 1.0_dp, w_re, v_im, 0.0_dp, tmp_kk)
1168 CALL dbcsr_add(p_im, tmp_kk, alpha_scalar=1.0_dp, beta_scalar=-1.0_dp)
1188 IF (qs_ot_env%settings%do_rotation)
THEN
1191 CALL dbcsr_copy(rotated_re, matrix_c, name=
"rotated_re")
1192 CALL dbcsr_copy(rotated_im, matrix_c_im, name=
"rotated_im")
1193 CALL dbcsr_copy(rotation_tmp, matrix_c, name=
"rotation_tmp")
1197 qs_ot_env%rot_mat_u_im, rotated_re, rotated_im, rotation_tmp)
1206 DEALLOCATE (eigenvalues, inverse_sqrt)
1208 CALL timestop(handle)
1220 matrix_hc_rotation, matrix_hc_rotation_im)
1221 TYPE(
dbcsr_type),
POINTER :: matrix_hc, matrix_hc_im
1223 TYPE(
dbcsr_type),
OPTIONAL,
POINTER :: matrix_hc_rotation, matrix_hc_rotation_im
1225 CHARACTER(len=*),
PARAMETER :: routinen =
'qs_ot_get_derivative_ref_complex'
1227 INTEGER :: handle, k, n
1229 TYPE(
dbcsr_type),
POINTER :: b_im, b_re, f_im, f_re, g_im, g_re, hc_im, hc_re, &
1230 hc_rotation_im, hc_rotation_re, hc_work_im, hc_work_re, q_im, q_re, sc_im, sc_re, tmp_kk
1231 TYPE(
dbcsr_type),
TARGET :: hc_rot_im, hc_rot_re
1233 CALL timeset(routinen, handle)
1235 cpassert(qs_ot_env%has_complex_kpoint_state)
1236 cpassert(
ASSOCIATED(matrix_hc))
1237 cpassert(
ASSOCIATED(matrix_hc_im))
1239 f_re => qs_ot_env%matrix_ref_inv_sqrt
1240 f_im => qs_ot_env%matrix_ref_inv_sqrt_im
1241 sc_re => qs_ot_env%matrix_sx
1242 sc_im => qs_ot_env%matrix_sx_im
1244 hc_im => matrix_hc_im
1245 hc_rotation_re => hc_re
1246 hc_rotation_im => hc_im
1247 IF (
PRESENT(matrix_hc_rotation) .OR.
PRESENT(matrix_hc_rotation_im))
THEN
1248 cpassert(
PRESENT(matrix_hc_rotation) .AND.
PRESENT(matrix_hc_rotation_im))
1249 cpassert(
ASSOCIATED(matrix_hc_rotation))
1250 cpassert(
ASSOCIATED(matrix_hc_rotation_im))
1251 hc_rotation_re => matrix_hc_rotation
1252 hc_rotation_im => matrix_hc_rotation_im
1256 g_re => qs_ot_env%matrix_gx
1257 g_im => qs_ot_env%matrix_gx_im
1258 b_re => qs_ot_env%buf1_k_k_sym
1259 b_im => qs_ot_env%buf2_k_k_sym
1260 tmp_kk => qs_ot_env%buf3_k_k_sym
1261 q_re => qs_ot_env%buf1_n_k
1262 q_im => qs_ot_env%buf1_n_k_dp
1267 CALL qs_ot_complex_multiply(
'N',
'N', qs_ot_env%matrix_x, qs_ot_env%matrix_x_im, f_re, f_im, q_re, q_im, &
1270 IF (qs_ot_env%settings%do_rotation)
THEN
1275 0.0_dp, qs_ot_env%rot_mat_dedu)
1276 CALL dbcsr_multiply(
'T',
'N', 1.0_dp, q_im, hc_rotation_im, 0.0_dp, tmp_kk)
1277 CALL dbcsr_add(qs_ot_env%rot_mat_dedu, tmp_kk, &
1278 alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
1281 0.0_dp, qs_ot_env%rot_mat_dedu_im)
1282 CALL dbcsr_multiply(
'T',
'N', 1.0_dp, q_im, hc_rotation_re, 0.0_dp, tmp_kk)
1283 CALL dbcsr_add(qs_ot_env%rot_mat_dedu_im, tmp_kk, &
1284 alpha_scalar=1.0_dp, beta_scalar=-1.0_dp)
1288 CALL dbcsr_copy(hc_rot_re, hc_re, name=
"hc_rot_re")
1289 CALL dbcsr_copy(hc_rot_im, hc_im, name=
"hc_rot_im")
1290 CALL dbcsr_copy(tmp_nk, hc_re, name=
"tmp_nk")
1291 CALL dbcsr_multiply(
'N',
'T', 1.0_dp, hc_re, qs_ot_env%rot_mat_u, &
1293 CALL dbcsr_multiply(
'N',
'T', 1.0_dp, hc_im, qs_ot_env%rot_mat_u_im, &
1295 CALL dbcsr_add(hc_rot_re, tmp_nk, alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
1297 CALL dbcsr_multiply(
'N',
'T', 1.0_dp, hc_im, qs_ot_env%rot_mat_u, &
1299 CALL dbcsr_multiply(
'N',
'T', 1.0_dp, hc_re, qs_ot_env%rot_mat_u_im, &
1301 CALL dbcsr_add(hc_rot_im, tmp_nk, alpha_scalar=1.0_dp, beta_scalar=-1.0_dp)
1302 hc_work_re => hc_rot_re
1303 hc_work_im => hc_rot_im
1307 CALL dbcsr_multiply(
'T',
'N', 1.0_dp, q_re, hc_work_re, 0.0_dp, b_re)
1308 CALL dbcsr_multiply(
'T',
'N', 1.0_dp, q_im, hc_work_im, 0.0_dp, tmp_kk)
1309 CALL dbcsr_add(b_re, tmp_kk, alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
1311 CALL dbcsr_multiply(
'T',
'N', 1.0_dp, q_re, hc_work_im, 0.0_dp, b_im)
1312 CALL dbcsr_multiply(
'T',
'N', 1.0_dp, q_im, hc_work_re, 0.0_dp, tmp_kk)
1313 CALL dbcsr_add(b_im, tmp_kk, alpha_scalar=1.0_dp, beta_scalar=-1.0_dp)
1315 IF (qs_ot_env%settings%eps_irac_filter_matrix > 0.0_dp)
THEN
1316 CALL dbcsr_filter(b_re, qs_ot_env%settings%eps_irac_filter_matrix)
1317 CALL dbcsr_filter(b_im, qs_ot_env%settings%eps_irac_filter_matrix)
1326 CALL dbcsr_add(q_re, q_im, alpha_scalar=1.0_dp, beta_scalar=-1.0_dp)
1330 CALL dbcsr_add(q_im, g_re, alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
1332 CALL dbcsr_add(q_re, hc_work_re, alpha_scalar=-1.0_dp, beta_scalar=1.0_dp)
1333 CALL dbcsr_add(q_im, hc_work_im, alpha_scalar=-1.0_dp, beta_scalar=1.0_dp)
1338 CALL dbcsr_add(g_re, g_im, alpha_scalar=1.0_dp, beta_scalar=-1.0_dp)
1342 CALL dbcsr_add(g_im, q_re, alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
1344 IF (qs_ot_env%settings%do_rotation)
THEN
1345 CALL qs_ot_add_ref_vertical_response_complex(b_re, b_im, f_re, f_im, &
1346 sc_re, sc_im, g_re, g_im, qs_ot_env)
1349 IF (qs_ot_env%settings%eps_irac_filter_matrix > 0.0_dp)
THEN
1350 CALL dbcsr_filter(g_re, qs_ot_env%settings%eps_irac_filter_matrix)
1351 CALL dbcsr_filter(g_im, qs_ot_env%settings%eps_irac_filter_matrix)
1354 IF (qs_ot_env%settings%do_rotation)
THEN
1360 CALL timestop(handle)
1376 SUBROUTINE qs_ot_add_ref_vertical_response_complex(a_re, a_im, f_re, f_im, &
1377 sx_re, sx_im, gradient_re, gradient_im, &
1379 TYPE(
dbcsr_type) :: a_re, a_im, f_re, f_im, sx_re, sx_im, &
1380 gradient_re, gradient_im
1383 CHARACTER(len=*),
PARAMETER :: routinen =
'qs_ot_add_ref_vertical_response_complex'
1385 INTEGER :: col, handle, i, j, k, row
1386 INTEGER,
DIMENSION(:),
POINTER :: col_blk_offset, row_blk_offset
1387 LOGICAL :: found_im, found_re
1388 REAL(kind=
dp) :: denominator
1389 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: f_evals
1390 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: block_im, block_re
1392 TYPE(
dbcsr_type) :: anti_im, anti_re, f_work_im, f_work_re, inner_im, inner_re, sq_im, &
1393 sq_re, tmp_kk, tmp_nk, v_im, v_re, vertical_im, vertical_re, work_im, work_re, z_im, z_re
1395 CALL timeset(routinen, handle)
1399 CALL timestop(handle)
1406 CALL dbcsr_copy(anti_re, a_re, name=
'anti_re')
1407 CALL dbcsr_add(anti_re, tmp_kk, alpha_scalar=0.5_dp, beta_scalar=-0.5_dp)
1409 CALL dbcsr_copy(anti_im, a_im, name=
'anti_im')
1410 CALL dbcsr_add(anti_im, tmp_kk, alpha_scalar=0.5_dp, beta_scalar=0.5_dp)
1414 CALL dbcsr_copy(f_work_re, f_re, name=
'f_work_re')
1415 CALL dbcsr_copy(f_work_im, f_im, name=
'f_work_im')
1418 ALLOCATE (f_evals(k))
1420 eigenvectors_re=v_re, eigenvectors_im=v_im, eigenvalues=f_evals, &
1421 para_env=qs_ot_env%para_env, blacs_env=qs_ot_env%blacs_env)
1422 IF (minval(f_evals) <= epsilon(1.0_dp))
THEN
1423 cpabort(
'Complex REF inverse square root is not positive definite')
1427 CALL dbcsr_copy(work_re, anti_re, name=
'work_re')
1428 CALL dbcsr_copy(work_im, anti_im, name=
'work_im')
1431 CALL dbcsr_copy(inner_re, anti_re, name=
'inner_re')
1432 CALL dbcsr_copy(inner_im, anti_im, name=
'inner_im')
1433 CALL dbcsr_multiply(
'T',
'N', 1.0_dp, v_re, work_re, 0.0_dp, inner_re)
1434 CALL dbcsr_multiply(
'T',
'N', 1.0_dp, v_im, work_im, 1.0_dp, inner_re)
1435 CALL dbcsr_multiply(
'T',
'N', 1.0_dp, v_re, work_im, 0.0_dp, inner_im)
1436 CALL dbcsr_multiply(
'T',
'N', -1.0_dp, v_im, work_re, 1.0_dp, inner_im)
1439 col_blk_offset=col_blk_offset)
1445 cpassert(found_re .AND. found_im)
1446 DO i = 1,
SIZE(block_re, 1)
1447 DO j = 1,
SIZE(block_re, 2)
1448 denominator = 1.0_dp/f_evals(row_blk_offset(row) + i - 1) + &
1449 1.0_dp/f_evals(col_blk_offset(col) + j - 1)
1450 block_re(i, j) = block_re(i, j)/denominator
1451 block_im(i, j) = block_im(i, j)/denominator
1462 CALL dbcsr_multiply(
'N',
'T', 1.0_dp, work_re, v_re, 0.0_dp, z_re)
1463 CALL dbcsr_multiply(
'N',
'T', 1.0_dp, work_im, v_im, 1.0_dp, z_re)
1464 CALL dbcsr_multiply(
'N',
'T', 1.0_dp, work_im, v_re, 0.0_dp, z_im)
1465 CALL dbcsr_multiply(
'N',
'T', -1.0_dp, work_re, v_im, 1.0_dp, z_im)
1470 CALL dbcsr_copy(tmp_nk, sx_re, name=
'tmp_nk')
1473 CALL dbcsr_copy(vertical_re, sx_re, name=
'vertical_re')
1474 CALL dbcsr_copy(vertical_im, sx_im, name=
'vertical_im')
1476 CALL dbcsr_add(gradient_re, vertical_re, alpha_scalar=1.0_dp, beta_scalar=2.0_dp)
1477 CALL dbcsr_add(gradient_im, vertical_im, alpha_scalar=1.0_dp, beta_scalar=2.0_dp)
1479 DEALLOCATE (f_evals)
1499 CALL timestop(handle)
1501 END SUBROUTINE qs_ot_add_ref_vertical_response_complex
1512 CHARACTER(len=*),
PARAMETER :: routinen =
'qs_ot_generate_rotation_complex'
1514 INTEGER :: handle, k
1515 REAL(kind=
dp) :: rot_norm
1516 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: exp_evals_im, exp_evals_re
1519 CALL timeset(routinen, handle)
1521 cpassert(qs_ot_env%has_complex_kpoint_state)
1522 cpassert(
ASSOCIATED(qs_ot_env%rot_mat_x_im))
1523 cpassert(
ASSOCIATED(qs_ot_env%rot_mat_u_im))
1529 IF (rot_norm <= epsilon(1.0_dp))
THEN
1530 CALL dbcsr_set(qs_ot_env%rot_mat_u, 0.0_dp)
1532 CALL dbcsr_set(qs_ot_env%rot_mat_u_im, 0.0_dp)
1533 CALL timestop(handle)
1539 CALL dbcsr_copy(h_re, qs_ot_env%rot_mat_x_im, name=
"h_re")
1541 CALL cp_dbcsr_heevd(matrix_re=h_re, matrix_im=qs_ot_env%rot_mat_x, &
1542 eigenvectors_re=qs_ot_env%rot_mat_evec_re, &
1543 eigenvectors_im=qs_ot_env%rot_mat_evec_im, &
1544 eigenvalues=qs_ot_env%rot_mat_evals, &
1545 para_env=qs_ot_env%para_env, blacs_env=qs_ot_env%blacs_env)
1547 ALLOCATE (exp_evals_re(k), exp_evals_im(k))
1548 exp_evals_re(:) = cos(-qs_ot_env%rot_mat_evals(:))
1549 exp_evals_im(:) = sin(-qs_ot_env%rot_mat_evals(:))
1551 CALL dbcsr_copy(w_re, qs_ot_env%rot_mat_evec_re, name=
"w_re")
1553 CALL dbcsr_copy(tmp, qs_ot_env%rot_mat_evec_im, name=
"tmp")
1555 CALL dbcsr_add(w_re, tmp, alpha_scalar=1.0_dp, beta_scalar=-1.0_dp)
1557 CALL dbcsr_copy(w_im, qs_ot_env%rot_mat_evec_im, name=
"w_im")
1559 CALL dbcsr_copy(tmp, qs_ot_env%rot_mat_evec_re)
1561 CALL dbcsr_add(w_im, tmp, alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
1563 CALL dbcsr_multiply(
'N',
'T', 1.0_dp, w_re, qs_ot_env%rot_mat_evec_re, &
1564 0.0_dp, qs_ot_env%rot_mat_u)
1565 CALL dbcsr_multiply(
'N',
'T', 1.0_dp, w_im, qs_ot_env%rot_mat_evec_im, &
1566 1.0_dp, qs_ot_env%rot_mat_u)
1567 CALL dbcsr_multiply(
'N',
'T', 1.0_dp, w_im, qs_ot_env%rot_mat_evec_re, &
1568 0.0_dp, qs_ot_env%rot_mat_u_im)
1569 CALL dbcsr_multiply(
'N',
'T', -1.0_dp, w_re, qs_ot_env%rot_mat_evec_im, &
1570 1.0_dp, qs_ot_env%rot_mat_u_im)
1576 DEALLOCATE (exp_evals_re, exp_evals_im)
1579 CALL timestop(handle)
1591 CHARACTER(len=*),
PARAMETER :: routinen =
'qs_ot_rot_mat_derivative_complex'
1593 INTEGER :: handle, k
1594 REAL(kind=
dp) :: rot_norm
1595 TYPE(
dbcsr_type) :: frechet_im, frechet_re, inner_deriv_im, &
1596 inner_deriv_re, outer_deriv_im, &
1597 outer_deriv_re, tmp, work_im, work_re
1599 CALL timeset(routinen, handle)
1601 cpassert(qs_ot_env%has_complex_kpoint_state)
1602 cpassert(
ASSOCIATED(qs_ot_env%rot_mat_dedu_im))
1603 cpassert(
ASSOCIATED(qs_ot_env%rot_mat_gx_im))
1609 IF (rot_norm <= epsilon(1.0_dp))
THEN
1611 CALL dbcsr_copy(qs_ot_env%rot_mat_gx, qs_ot_env%rot_mat_dedu)
1612 CALL dbcsr_add(qs_ot_env%rot_mat_gx, tmp, &
1613 alpha_scalar=1.0_dp, beta_scalar=-1.0_dp)
1617 CALL dbcsr_copy(qs_ot_env%rot_mat_gx_im, qs_ot_env%rot_mat_dedu_im)
1618 CALL dbcsr_add(qs_ot_env%rot_mat_gx_im, tmp, &
1619 alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
1621 CALL timestop(handle)
1625 CALL dbcsr_copy(work_re, qs_ot_env%rot_mat_dedu, name=
"work_re")
1626 CALL dbcsr_copy(work_im, qs_ot_env%rot_mat_dedu, name=
"work_im")
1627 CALL dbcsr_copy(tmp, qs_ot_env%rot_mat_dedu, name=
"tmp")
1628 CALL dbcsr_copy(inner_deriv_re, qs_ot_env%rot_mat_dedu, name=
"inner_deriv_re")
1629 CALL dbcsr_copy(inner_deriv_im, qs_ot_env%rot_mat_dedu, name=
"inner_deriv_im")
1633 qs_ot_env%rot_mat_evec_re, qs_ot_env%rot_mat_evec_im, work_re, work_im, &
1635 CALL dbcsr_multiply(
'T',
'N', 1.0_dp, qs_ot_env%rot_mat_evec_re, &
1636 work_re, 0.0_dp, inner_deriv_re)
1637 CALL dbcsr_multiply(
'T',
'N', 1.0_dp, qs_ot_env%rot_mat_evec_im, &
1638 work_im, 1.0_dp, inner_deriv_re)
1639 CALL dbcsr_multiply(
'T',
'N', 1.0_dp, qs_ot_env%rot_mat_evec_re, &
1640 work_im, 0.0_dp, inner_deriv_im)
1641 CALL dbcsr_multiply(
'T',
'N', -1.0_dp, qs_ot_env%rot_mat_evec_im, &
1642 work_re, 1.0_dp, inner_deriv_im)
1645 inner_deriv_re, inner_deriv_im, &
1646 outer_deriv_re, outer_deriv_im, adjoint=.true.)
1649 outer_deriv_re, outer_deriv_im, work_re, work_im, tmp)
1651 CALL dbcsr_copy(frechet_re, qs_ot_env%rot_mat_dedu, name=
"frechet_re")
1652 CALL dbcsr_copy(frechet_im, qs_ot_env%rot_mat_dedu, name=
"frechet_im")
1653 CALL dbcsr_multiply(
'N',
'T', 1.0_dp, work_re, qs_ot_env%rot_mat_evec_re, &
1655 CALL dbcsr_multiply(
'N',
'T', 1.0_dp, work_im, qs_ot_env%rot_mat_evec_im, &
1657 CALL dbcsr_multiply(
'N',
'T', 1.0_dp, work_im, qs_ot_env%rot_mat_evec_re, &
1659 CALL dbcsr_multiply(
'N',
'T', -1.0_dp, work_re, qs_ot_env%rot_mat_evec_im, &
1664 CALL dbcsr_copy(qs_ot_env%rot_mat_gx, frechet_re)
1665 CALL dbcsr_add(qs_ot_env%rot_mat_gx, tmp, &
1666 alpha_scalar=1.0_dp, beta_scalar=-1.0_dp)
1668 CALL dbcsr_copy(qs_ot_env%rot_mat_gx_im, frechet_im)
1669 CALL dbcsr_add(qs_ot_env%rot_mat_gx_im, tmp, &
1670 alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
1683 CALL timestop(handle)
1697 TYPE(
dbcsr_type),
POINTER :: matrix_x, matrix_x_im, matrix_sx, &
1700 LOGICAL,
INTENT(IN),
OPTIONAL :: zero_coordinates
1702 CHARACTER(len=*),
PARAMETER :: routinen =
'qs_ot_get_p_complex'
1706 CALL timeset(routinen, handle)
1708 cpassert(qs_ot_env%has_complex_kpoint_state)
1709 cpassert(qs_ot_env%settings%ot_algorithm ==
'TOD')
1711 IF (
PRESENT(zero_coordinates))
THEN
1712 IF (zero_coordinates)
THEN
1713 CALL dbcsr_set(qs_ot_env%matrix_p, 0.0_dp)
1714 CALL dbcsr_set(qs_ot_env%matrix_p_im, 0.0_dp)
1715 CALL dbcsr_set(qs_ot_env%matrix_r, 0.0_dp)
1717 CALL dbcsr_set(qs_ot_env%matrix_r_im, 0.0_dp)
1718 CALL dbcsr_copy(qs_ot_env%matrix_cosp, qs_ot_env%matrix_r)
1719 CALL dbcsr_copy(qs_ot_env%matrix_sinp, qs_ot_env%matrix_r)
1720 CALL dbcsr_set(qs_ot_env%matrix_cosp_im, 0.0_dp)
1721 CALL dbcsr_set(qs_ot_env%matrix_sinp_im, 0.0_dp)
1724 CALL dbcsr_set(qs_ot_env%matrix_cosp_b, -0.5_dp)
1725 CALL dbcsr_set(qs_ot_env%matrix_sinp_b, -1.0_dp/6.0_dp)
1726 qs_ot_env%evals(:) = 0.0_dp
1727 qs_ot_env%dum(:) = 0.0_dp
1728 qs_ot_env%do_taylor = .false.
1729 CALL timestop(handle)
1735 qs_ot_env%matrix_p, qs_ot_env%matrix_p_im, qs_ot_env%matrix_buf1)
1736 qs_ot_env%do_taylor = .false.
1739 CALL timestop(handle)
1752 TYPE(
dbcsr_type),
POINTER :: matrix_c, matrix_c_im, matrix_s, &
1756 CHARACTER(len=*),
PARAMETER :: routinen =
'qs_ot_get_orbitals_complex'
1759 TYPE(
dbcsr_type) :: rotated_im, rotated_re, rotation_tmp
1761 CALL timeset(routinen, handle)
1763 cpassert(qs_ot_env%has_complex_kpoint_state)
1764 cpassert(qs_ot_env%settings%ot_algorithm ==
'TOD')
1767 qs_ot_env%matrix_x, qs_ot_env%matrix_x_im, &
1768 qs_ot_env%matrix_sx, qs_ot_env%matrix_sx_im, &
1769 qs_ot_env%matrix_tmp_nk)
1771 qs_ot_env%matrix_sx, qs_ot_env%matrix_sx_im, qs_ot_env)
1774 qs_ot_env%matrix_cosp, qs_ot_env%matrix_cosp_im, &
1775 matrix_c, matrix_c_im, qs_ot_env%matrix_tmp_nk)
1777 qs_ot_env%matrix_sinp, qs_ot_env%matrix_sinp_im, &
1778 qs_ot_env%matrix_buf_nk, qs_ot_env%matrix_buf_nk_im, &
1779 qs_ot_env%matrix_tmp_nk)
1780 CALL dbcsr_add(matrix_c, qs_ot_env%matrix_buf_nk, alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
1781 CALL dbcsr_add(matrix_c_im, qs_ot_env%matrix_buf_nk_im, alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
1783 IF (qs_ot_env%settings%do_rotation)
THEN
1786 CALL dbcsr_copy(rotated_re, matrix_c, name=
"strict_rotated_re")
1787 CALL dbcsr_copy(rotated_im, matrix_c_im, name=
"strict_rotated_im")
1788 CALL dbcsr_copy(rotation_tmp, matrix_c, name=
"strict_rotation_tmp")
1792 qs_ot_env%rot_mat_u_im, rotated_re, rotated_im, rotation_tmp)
1801 CALL timestop(handle)
1815 TYPE(
dbcsr_type),
OPTIONAL,
POINTER :: matrix_gx_im
1816 LOGICAL,
INTENT(IN),
OPTIONAL :: use_preconditioner
1818 LOGICAL :: preconditioned
1819 TYPE(
dbcsr_type),
POINTER :: target_im, target_re
1821 IF (.NOT. qs_ot_env%has_complex_kpoint_state)
THEN
1822 CALL qs_ot_project_gradient_real(qs_ot_env, matrix_gx, use_preconditioner)
1825 preconditioned = .true.
1826 IF (
PRESENT(use_preconditioner)) preconditioned = use_preconditioner
1827 IF (.NOT. preconditioned) qs_ot_env%os_valid = .false.
1828 cpassert(
PRESENT(matrix_gx_im))
1830 IF (preconditioned .AND.
ASSOCIATED(qs_ot_env%preconditioner))
THEN
1831 target_re => qs_ot_env%matrix_psc0
1832 target_im => qs_ot_env%matrix_psc0_im
1834 target_re => qs_ot_env%matrix_sc0
1835 target_im => qs_ot_env%matrix_sc0_im
1839 matrix_gx, matrix_gx_im, &
1840 qs_ot_env%matrix_buf1_ortho, qs_ot_env%matrix_buf1_ortho_im, &
1841 qs_ot_env%matrix_tmp_ortho)
1843 qs_ot_env%matrix_buf1_ortho, qs_ot_env%matrix_buf1_ortho_im, &
1844 qs_ot_env%matrix_buf2_ortho, qs_ot_env%matrix_buf2_ortho_im, &
1845 qs_ot_env%matrix_tmp_ortho)
1847 qs_ot_env%matrix_buf2_ortho, qs_ot_env%matrix_buf2_ortho_im, &
1848 qs_ot_env%matrix_buf_nk, qs_ot_env%matrix_buf_nk_im, &
1849 qs_ot_env%matrix_tmp_nk)
1850 CALL dbcsr_add(matrix_gx, qs_ot_env%matrix_buf_nk, &
1851 alpha_scalar=1.0_dp, beta_scalar=-1.0_dp)
1852 CALL dbcsr_add(matrix_gx_im, qs_ot_env%matrix_buf_nk_im, &
1853 alpha_scalar=1.0_dp, beta_scalar=-1.0_dp)
1866 LOGICAL,
INTENT(OUT),
OPTIONAL :: preconditioner_rejected
1867 LOGICAL,
INTENT(IN),
OPTIONAL :: use_preconditioner
1870 LOGICAL :: preconditioned
1871 REAL(kind=
dp) :: eval_scale, eval_threshold
1872 TYPE(
dbcsr_type),
POINTER :: target_im, target_re
1874 preconditioned = .true.
1875 IF (
PRESENT(use_preconditioner)) preconditioned = use_preconditioner
1876 IF (.NOT. preconditioned) qs_ot_env%os_valid = .false.
1877 IF (
PRESENT(preconditioner_rejected)) preconditioner_rejected = .false.
1878 IF (qs_ot_env%os_valid)
RETURN
1880 IF (preconditioned .AND.
ASSOCIATED(qs_ot_env%preconditioner))
THEN
1881 target_re => qs_ot_env%matrix_psc0
1882 target_im => qs_ot_env%matrix_psc0_im
1884 qs_ot_env%matrix_sc0, qs_ot_env%matrix_sc0_im, &
1885 target_re, target_im)
1887 target_re => qs_ot_env%matrix_sc0
1888 target_im => qs_ot_env%matrix_sc0_im
1891 target_re, target_im, qs_ot_env%matrix_os, qs_ot_env%matrix_os_im, &
1892 qs_ot_env%matrix_buf1)
1895 CALL cp_dbcsr_heevd(matrix_re=qs_ot_env%matrix_os, matrix_im=qs_ot_env%matrix_os_im, &
1896 eigenvectors_re=qs_ot_env%matrix_buf3, eigenvectors_im=qs_ot_env%matrix_buf3_im, &
1897 eigenvalues=qs_ot_env%dum, para_env=qs_ot_env%para_env, &
1898 blacs_env=qs_ot_env%blacs_env)
1899 eval_scale = max(1.0_dp, maxval(abs(qs_ot_env%dum(1:k))))
1900 eval_threshold = 100.0_dp*epsilon(1.0_dp)*eval_scale
1901 IF (minval(qs_ot_env%dum(1:k)) <= eval_threshold .AND. &
1902 preconditioned .AND.
ASSOCIATED(qs_ot_env%preconditioner))
THEN
1903 NULLIFY (qs_ot_env%preconditioner)
1904 qs_ot_env%preconditioner_changed = .true.
1905 IF (
PRESENT(preconditioner_rejected)) preconditioner_rejected = .true.
1906 target_re => qs_ot_env%matrix_sc0
1907 target_im => qs_ot_env%matrix_sc0_im
1909 target_re, target_im, qs_ot_env%matrix_os, qs_ot_env%matrix_os_im, &
1910 qs_ot_env%matrix_buf1)
1911 CALL cp_dbcsr_heevd(matrix_re=qs_ot_env%matrix_os, matrix_im=qs_ot_env%matrix_os_im, &
1912 eigenvectors_re=qs_ot_env%matrix_buf3, eigenvectors_im=qs_ot_env%matrix_buf3_im, &
1913 eigenvalues=qs_ot_env%dum, para_env=qs_ot_env%para_env, &
1914 blacs_env=qs_ot_env%blacs_env)
1915 eval_scale = max(1.0_dp, maxval(abs(qs_ot_env%dum(1:k))))
1916 eval_threshold = 100.0_dp*epsilon(1.0_dp)*eval_scale
1918 cpassert(minval(qs_ot_env%dum(1:k)) > eval_threshold)
1920 qs_ot_env%dum(i) = 1.0_dp/qs_ot_env%dum(i)
1922 CALL dbcsr_copy(qs_ot_env%matrix_buf1, qs_ot_env%matrix_buf3)
1923 CALL dbcsr_copy(qs_ot_env%matrix_buf1_im, qs_ot_env%matrix_buf3_im)
1927 qs_ot_env%matrix_buf3, qs_ot_env%matrix_buf3_im, &
1928 qs_ot_env%matrix_os, qs_ot_env%matrix_os_im, &
1929 qs_ot_env%matrix_buf2)
1931 qs_ot_env%os_valid = preconditioned
1942 TYPE(
qs_ot_type),
INTENT(INOUT) :: qs_ot_env(:)
1944 INTEGER :: first, i, j, k, n, nbatch, nchannels, &
1946 INTEGER,
ALLOCATABLE :: channels(:)
1948 REAL(
dp) :: eval_threshold
1949 TYPE(
dbcsr_p_type),
ALLOCATABLE :: matrix_in(:, :), matrix_out(:, :)
1951 TYPE(qs_ot_local_work_type),
ALLOCATABLE :: work(:)
1953 IF (.NOT. qs_ot_local_channels(qs_ot_env))
RETURN
1954 IF (.NOT. qs_ot_env(1)%settings%ks .OR. qs_ot_env(1)%settings%ot_algorithm /=
'TOD')
RETURN
1956 nchannels = count(.NOT. qs_ot_env(:)%os_valid)
1957 IF (nchannels == 0)
RETURN
1958 ALLOCATE (channels(nchannels))
1960 DO i = 1,
SIZE(qs_ot_env)
1961 IF (qs_ot_env(i)%os_valid) cycle
1967 ALLOCATE (work(nworkers), preconditioners(nworkers), &
1968 matrix_in(2, nworkers), matrix_out(2, nworkers))
1972 DO first = 1, nchannels, nworkers
1973 nbatch = min(nworkers, nchannels - first + 1)
1975 i = channels(first + j - 1)
1976 preconditioners(j)%preconditioner => qs_ot_env(i)%preconditioner
1977 matrix_in(1, j)%matrix => qs_ot_env(i)%matrix_sc0
1978 matrix_in(2, j)%matrix => qs_ot_env(i)%matrix_sc0_im
1979 matrix_out(:, j) = matrix_in(:, j)
1980 IF (
ASSOCIATED(qs_ot_env(i)%preconditioner))
THEN
1981 matrix_out(1, j)%matrix => qs_ot_env(i)%matrix_psc0
1982 matrix_out(2, j)%matrix => qs_ot_env(i)%matrix_psc0_im
1985 CALL apply_preconditioner_complex_batch(preconditioners(1:nbatch), &
1986 matrix_in(:, 1:nbatch), matrix_out(:, 1:nbatch), handled)
1988 IF (.NOT. handled .AND.
ASSOCIATED(preconditioners(j)%preconditioner))
THEN
1990 matrix_in(1, j)%matrix, matrix_in(2, j)%matrix, &
1991 matrix_out(1, j)%matrix, matrix_out(2, j)%matrix)
1993 CALL dbcsr_get_info(matrix_in(1, j)%matrix, nfullrows_total=n, nfullcols_total=k)
1994 IF (
ALLOCATED(work(j)%sc0))
THEN
1995 IF (n /= work(j)%n .OR. k /= work(j)%k)
THEN
1996 DEALLOCATE (work(j)%sc0, work(j)%target, work(j)%os, work(j)%r, &
1997 work(j)%buf1, work(j)%buf2, work(j)%vectors, work(j)%values)
2000 IF (.NOT.
ALLOCATED(work(j)%sc0))
THEN
2001 ALLOCATE (work(j)%sc0(n, k, 2), work(j)%target(n, k, 2), work(j)%os(k, k, 2), &
2002 work(j)%r(k, k, 2), work(j)%buf1(k, k, 2), work(j)%buf2(k, k, 2), &
2003 work(j)%vectors(k, k), work(j)%values(k))
2008 CALL qs_ot_load_local_pair(matrix_in(1, j)%matrix, matrix_in(2, j)%matrix, work(j)%sc0)
2009 CALL qs_ot_load_local_pair(matrix_out(1, j)%matrix, matrix_out(2, j)%matrix, work(j)%target)
2014 CALL qs_ot_complex_multiply_local(
'C',
'N', work(j)%sc0, work(j)%target, &
2015 work(j)%os, work(j)%buf2(:, :, 1), work(j)%gemm_ctx)
2016 work(j)%vectors(:, :) = cmplx(work(j)%os(:, :, 1), work(j)%os(:, :, 2), kind=
dp)
2018 IF (work(j)%info /= 0) cycle
2019 eval_threshold = 100.0_dp*epsilon(1.0_dp)*max(1.0_dp, maxval(abs(work(j)%solver%evals)))
2020 IF (minval(work(j)%solver%evals) <= eval_threshold)
THEN
2024 work(j)%values(:) = 1.0_dp/work(j)%solver%evals(:)
2025 work(j)%r(:, :, 1) = real(work(j)%vectors, kind=
dp)
2026 work(j)%r(:, :, 2) = aimag(work(j)%vectors)
2027 CALL qs_ot_spectral_matrix_local(work(j), matrix=work(j)%os)
2031 IF (work(j)%info /= 0) cycle
2032 i = channels(first + j - 1)
2033 CALL qs_ot_store_local_pair(qs_ot_env(i)%matrix_os, qs_ot_env(i)%matrix_os_im, work(j)%os)
2034 qs_ot_env(i)%os_valid = .true.
2038 CALL work(j)%gemm_ctx%destroy()
2051 matrix_hc_rotation, matrix_hc_rotation_im)
2052 TYPE(
dbcsr_type),
POINTER :: matrix_hc, matrix_hc_im
2054 TYPE(
dbcsr_type),
OPTIONAL,
POINTER :: matrix_hc_rotation, matrix_hc_rotation_im
2056 CHARACTER(len=*),
PARAMETER :: routinen =
'qs_ot_get_derivative_complex'
2061 TYPE(
dbcsr_type),
POINTER :: hc_rotation_im, hc_rotation_re, &
2062 hc_work_im, hc_work_re
2063 TYPE(
dbcsr_type),
TARGET :: hc_rot_im, hc_rot_re
2065 CALL timeset(routinen, handle)
2067 cpassert(qs_ot_env%has_complex_kpoint_state)
2068 cpassert(qs_ot_env%settings%ot_algorithm ==
'TOD')
2070 hc_rotation_re => matrix_hc
2071 hc_rotation_im => matrix_hc_im
2072 IF (
PRESENT(matrix_hc_rotation) .OR.
PRESENT(matrix_hc_rotation_im))
THEN
2073 cpassert(
PRESENT(matrix_hc_rotation) .AND.
PRESENT(matrix_hc_rotation_im))
2074 cpassert(
ASSOCIATED(matrix_hc_rotation))
2075 cpassert(
ASSOCIATED(matrix_hc_rotation_im))
2076 hc_rotation_re => matrix_hc_rotation
2077 hc_rotation_im => matrix_hc_rotation_im
2079 hc_work_re => matrix_hc
2080 hc_work_im => matrix_hc_im
2082 IF (qs_ot_env%settings%do_rotation)
THEN
2087 qs_ot_env%matrix_cosp, qs_ot_env%matrix_cosp_im, &
2088 qs_ot_env%matrix_buf_nk, qs_ot_env%matrix_buf_nk_im, &
2089 qs_ot_env%matrix_tmp_nk)
2091 qs_ot_env%matrix_sinp, qs_ot_env%matrix_sinp_im, &
2092 qs_ot_env%matrix_gx, qs_ot_env%matrix_gx_im, &
2093 qs_ot_env%matrix_tmp_nk)
2094 CALL dbcsr_add(qs_ot_env%matrix_buf_nk, qs_ot_env%matrix_gx, &
2095 alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
2096 CALL dbcsr_add(qs_ot_env%matrix_buf_nk_im, qs_ot_env%matrix_gx_im, &
2097 alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
2101 qs_ot_env%matrix_buf_nk, qs_ot_env%matrix_buf_nk_im, &
2102 hc_rotation_re, hc_rotation_im, &
2103 qs_ot_env%rot_mat_dedu, qs_ot_env%rot_mat_dedu_im, &
2104 qs_ot_env%matrix_buf1)
2108 CALL dbcsr_copy(hc_rot_re, matrix_hc, name=
"strict_hc_rot_re")
2109 CALL dbcsr_copy(hc_rot_im, matrix_hc_im, name=
"strict_hc_rot_im")
2110 CALL dbcsr_copy(tmp_nk, matrix_hc, name=
"strict_hc_rot_tmp")
2111 CALL dbcsr_multiply(
'N',
'T', 1.0_dp, matrix_hc, qs_ot_env%rot_mat_u, &
2113 CALL dbcsr_multiply(
'N',
'T', 1.0_dp, matrix_hc_im, qs_ot_env%rot_mat_u_im, &
2115 CALL dbcsr_add(hc_rot_re, tmp_nk, alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
2117 CALL dbcsr_multiply(
'N',
'T', 1.0_dp, matrix_hc_im, qs_ot_env%rot_mat_u, &
2119 CALL dbcsr_multiply(
'N',
'T', 1.0_dp, matrix_hc, qs_ot_env%rot_mat_u_im, &
2121 CALL dbcsr_add(hc_rot_im, tmp_nk, alpha_scalar=1.0_dp, beta_scalar=-1.0_dp)
2122 hc_work_re => hc_rot_re
2123 hc_work_im => hc_rot_im
2128 qs_ot_env%matrix_sinp, qs_ot_env%matrix_sinp_im, &
2129 qs_ot_env%matrix_gx, qs_ot_env%matrix_gx_im, &
2130 qs_ot_env%matrix_tmp_nk)
2132 CALL qs_ot_strict_frechet(hc_work_re, hc_work_im, qs_ot_env%matrix_x, qs_ot_env%matrix_x_im, &
2133 qs_ot_env%matrix_sinp_b, qs_ot_env%matrix_buf3, qs_ot_env%matrix_buf3_im, qs_ot_env)
2134 CALL qs_ot_strict_frechet(hc_work_re, hc_work_im, qs_ot_env%matrix_c0, qs_ot_env%matrix_c0_im, &
2135 qs_ot_env%matrix_cosp_b, qs_ot_env%matrix_buf4, qs_ot_env%matrix_buf4_im, qs_ot_env)
2136 CALL dbcsr_add(qs_ot_env%matrix_buf3, qs_ot_env%matrix_buf4, &
2137 alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
2138 CALL dbcsr_add(qs_ot_env%matrix_buf3_im, qs_ot_env%matrix_buf4_im, &
2139 alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
2143 qs_ot_env%matrix_buf3, qs_ot_env%matrix_buf3_im, &
2144 qs_ot_env%matrix_buf1, qs_ot_env%matrix_buf1_im, &
2145 qs_ot_env%matrix_buf2)
2147 qs_ot_env%matrix_r, qs_ot_env%matrix_r_im, &
2148 qs_ot_env%matrix_buf3, qs_ot_env%matrix_buf3_im, &
2149 qs_ot_env%matrix_buf2)
2152 shallow_data_copy=.false., use_distribution=dist, &
2153 transpose_distribution=.false.)
2154 CALL dbcsr_transposed(qs_ot_env%matrix_buf4_im, qs_ot_env%matrix_buf3_im, &
2155 shallow_data_copy=.false., use_distribution=dist, &
2156 transpose_distribution=.false.)
2157 CALL dbcsr_add(qs_ot_env%matrix_buf3, qs_ot_env%matrix_buf4, &
2158 alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
2159 CALL dbcsr_add(qs_ot_env%matrix_buf3_im, qs_ot_env%matrix_buf4_im, &
2160 alpha_scalar=1.0_dp, beta_scalar=-1.0_dp)
2163 qs_ot_env%matrix_buf3, qs_ot_env%matrix_buf3_im, &
2164 qs_ot_env%matrix_buf_nk, qs_ot_env%matrix_buf_nk_im, &
2165 qs_ot_env%matrix_tmp_nk)
2166 CALL dbcsr_add(qs_ot_env%matrix_gx, qs_ot_env%matrix_buf_nk, &
2167 alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
2168 CALL dbcsr_add(qs_ot_env%matrix_gx_im, qs_ot_env%matrix_buf_nk_im, &
2169 alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
2173 IF (qs_ot_env%settings%do_rotation)
THEN
2179 CALL timestop(handle)
2188 LOGICAL FUNCTION qs_ot_local_channels(qs_ot_env)
RESULT(local)
2194 IF (
SIZE(qs_ot_env) == 0)
RETURN
2195 DO i = 1,
SIZE(qs_ot_env)
2196 IF (.NOT. qs_ot_env(i)%has_complex_kpoint_state)
RETURN
2197 IF (qs_ot_env(i)%settings%do_rotation)
RETURN
2198 SELECT CASE (qs_ot_env(i)%settings%ot_algorithm)
2200 IF (qs_ot_env(i)%settings%do_ener)
RETURN
2205 IF (qs_ot_env(i)%settings%ot_algorithm /= qs_ot_env(1)%settings%ot_algorithm)
RETURN
2206 IF (qs_ot_env(i)%para_env%num_pe /= 1)
RETURN
2209 END FUNCTION qs_ot_local_channels
2221 TYPE(
qs_ot_type),
INTENT(INOUT) :: qs_ot_env(:)
2224 LOGICAL,
INTENT(OUT) :: handled
2225 LOGICAL,
INTENT(IN),
OPTIONAL :: initialize
2227 CHARACTER(LEN=*),
PARAMETER :: routinen =
'qs_ot_get_orbitals_local_batch'
2229 INTEGER :: first, handle, i, j, k, n, nbatch, &
2231 LOGICAL :: initial, ref, update
2232 TYPE(qs_ot_local_work_type),
ALLOCATABLE :: work(:)
2235 IF (
PRESENT(initialize)) initial = initialize
2237 IF (.NOT. qs_ot_local_channels(qs_ot_env))
RETURN
2238 ref = qs_ot_env(1)%settings%ot_algorithm ==
'REF'
2241 CALL timeset(routinen, handle)
2242 nchannels =
SIZE(qs_ot_env)
2245 ALLOCATE (work(nworkers))
2249 DO first = 1, nchannels, nworkers
2250 nbatch = min(nworkers, nchannels - first + 1)
2253 CALL dbcsr_get_info(qs_ot_env(i)%matrix_x, nfullrows_total=n, nfullcols_total=k)
2254 CALL qs_ot_allocate_local_work(work(j), n, k)
2255 IF (.NOT. initial .OR. ref)
THEN
2256 IF (
ALLOCATED(work(j)%vectors))
THEN
2257 IF (
SIZE(work(j)%vectors, 1) /= k)
DEALLOCATE (work(j)%vectors, work(j)%values)
2259 IF (.NOT.
ALLOCATED(work(j)%vectors))
ALLOCATE (work(j)%vectors(k, k), work(j)%values(k))
2263 work(j)%x(:, :, 1) = real(matrix_c(i)%matrix%local_data(1:n, 1:k), kind=
dp)
2264 work(j)%x(:, :, 2) = aimag(matrix_c(i)%matrix%local_data(1:n, 1:k))
2266 CALL qs_ot_load_local_pair(qs_ot_env(i)%matrix_x, qs_ot_env(i)%matrix_x_im, work(j)%x)
2268 CALL qs_ot_load_local_pair(qs_ot_env(i)%matrix_c0, qs_ot_env(i)%matrix_c0_im, work(j)%c0)
2276 CALL qs_ot_orbitals_local(work(j), matrix_s(1, i)%matrix%local_data, &
2277 matrix_s(2, i)%matrix%local_data, ref, update, initial)
2278 IF (work(j)%info /= 0) cycle
2282 matrix_c(i)%matrix%local_data(1:n, 1:k) = cmplx(work(j)%out(:, :, 1), work(j)%out(:, :, 2), kind=
dp)
2286 IF (work(j)%info == -1) cpabort(
'Complex REF overlap is not positive definite')
2287 IF (work(j)%info /= 0) cpabort(
'Local complex OT overlap diagonalization failed')
2290 CALL qs_ot_store_local_pair(qs_ot_env(i)%matrix_c0, qs_ot_env(i)%matrix_c0_im, work(j)%out)
2291 CALL qs_ot_store_local_pair(qs_ot_env(i)%matrix_sc0, qs_ot_env(i)%matrix_sc0_im, work(j)%buf_nk)
2292 IF (.NOT. ref) cycle
2294 CALL qs_ot_store_local_pair(qs_ot_env(i)%matrix_sx, qs_ot_env(i)%matrix_sx_im, work(j)%sx)
2296 CALL qs_ot_store_local_pair(qs_ot_env(i)%matrix_ref_inv_sqrt, &
2297 qs_ot_env(i)%matrix_ref_inv_sqrt_im, work(j)%sinp)
2298 IF (update .OR. initial)
CALL qs_ot_store_local_pair(qs_ot_env(i)%matrix_x, qs_ot_env(i)%matrix_x_im, work(j)%x)
2301 CALL qs_ot_store_local_pair(qs_ot_env(i)%matrix_p, qs_ot_env(i)%matrix_p_im, work(j)%buf3)
2302 CALL qs_ot_store_local_pair(qs_ot_env(i)%matrix_r, qs_ot_env(i)%matrix_r_im, work(j)%r)
2303 CALL qs_ot_store_local_pair(qs_ot_env(i)%matrix_cosp, qs_ot_env(i)%matrix_cosp_im, work(j)%buf4)
2304 CALL qs_ot_store_local_pair(qs_ot_env(i)%matrix_sinp, qs_ot_env(i)%matrix_sinp_im, work(j)%sinp)
2307 qs_ot_env(i)%evals(:) = work(j)%solver%evals(:)
2308 qs_ot_env(i)%do_taylor = .false.
2312 CALL work(j)%gemm_ctx%destroy()
2315 CALL timestop(handle)
2327 SUBROUTINE qs_ot_orbitals_local(w, overlap_re, overlap_im, ref, update, initialize)
2328 TYPE(qs_ot_local_work_type),
INTENT(INOUT) :: w
2329 REAL(
dp),
CONTIGUOUS,
INTENT(IN) :: overlap_re(:, :), overlap_im(:, :)
2330 LOGICAL,
INTENT(IN) :: ref, update
2331 LOGICAL,
INTENT(IN),
OPTIONAL :: initialize
2335 CALL qs_ot_complex_multiply_local(
'N',
'N', overlap_re, overlap_im, w%x(:, :, 1), w%x(:, :, 2), &
2336 w%sx(:, :, 1), w%sx(:, :, 2), w%tmp, w%gemm_ctx)
2337 IF (
PRESENT(initialize))
THEN
2338 IF (initialize)
THEN
2341 w%buf_nk(:, :, :) = w%sx(:, :, :)
2343 w%out(:, :, :) = w%x(:, :, :)
2349 CALL qs_ot_complex_multiply_local(
'C',
'N', w%x, w%sx, w%buf3, w%buf2(:, :, 1), w%gemm_ctx)
2350 w%vectors(:, :) = cmplx(w%buf3(:, :, 1), w%buf3(:, :, 2), kind=
dp)
2352 IF (w%info /= 0)
RETURN
2353 w%r(:, :, 1) = real(w%vectors, kind=
dp)
2354 w%r(:, :, 2) = aimag(w%vectors)
2356 IF (any(w%solver%evals <= epsilon(1.0_dp)))
THEN
2360 w%values(:) = 1.0_dp/sqrt(w%solver%evals(:))
2361 CALL qs_ot_spectral_matrix_local(w, matrix=w%sinp)
2362 CALL qs_ot_complex_multiply_local(
'N',
'N', w%x, w%sinp, w%out, w%tmp, w%gemm_ctx)
2364 w%x(:, :, :) = w%out(:, :, :)
2365 w%sinp(:, :, :) = 0.0_dp
2367 w%sinp(i, i, 1) = 1.0_dp
2369 CALL qs_ot_complex_multiply_local(
'N',
'N', overlap_re, overlap_im, w%x(:, :, 1), w%x(:, :, 2), &
2370 w%sx(:, :, 1), w%sx(:, :, 2), w%tmp, w%gemm_ctx)
2374 w%solver%evals(:) = max(0.0_dp, w%solver%evals(:))
2375 CALL qs_ot_spectral_matrix_local(w, .true., w%buf4)
2376 CALL qs_ot_spectral_matrix_local(w, .false., w%sinp)
2377 w%values(:) = sqrt(w%solver%evals(:))
2380 CALL qs_ot_complex_multiply_local(
'N',
'N', w%c0, w%buf4, w%out, w%tmp, w%gemm_ctx)
2381 CALL qs_ot_complex_multiply_local(
'N',
'N', w%x, w%sinp, w%buf_nk, w%tmp, w%gemm_ctx)
2382 w%out(:, :, :) = w%out(:, :, :) + w%buf_nk(:, :, :)
2383 END SUBROUTINE qs_ot_orbitals_local
2391 SUBROUTINE qs_ot_spectral_matrix_local(w, cosine, matrix)
2392 TYPE(qs_ot_local_work_type),
INTENT(INOUT) :: w
2393 LOGICAL,
INTENT(IN),
OPTIONAL :: cosine
2394 REAL(
dp),
CONTIGUOUS,
INTENT(INOUT) :: matrix(:, :, :)
2400 w%buf1(:, i, 1) = w%r(:, i, 1)*w%values(i)
2401 w%buf1(:, i, 2) = w%r(:, i, 2)*w%values(i)
2403 CALL qs_ot_complex_multiply_local(
'N',
'C', w%buf1, w%r, matrix, w%buf2(:, :, 1), w%gemm_ctx)
2404 END SUBROUTINE qs_ot_spectral_matrix_local
2412 SUBROUTINE qs_ot_allocate_local_work(w, n, k)
2413 TYPE(qs_ot_local_work_type),
INTENT(INOUT) :: w
2414 INTEGER,
INTENT(IN) :: n, k
2416 IF (
ALLOCATED(w%x))
THEN
2417 IF (n == w%n .AND. k == w%k)
RETURN
2418 DEALLOCATE (w%x, w%sx, w%c0, w%out, w%r, w%sinp, w%buf1, w%buf2, w%buf3, w%buf4, &
2419 w%buf_nk, w%sinp_b, w%cosp_b, w%tmp)
2421 ALLOCATE (w%x(n, k, 2), w%sx(n, k, 2), w%c0(n, k, 2), w%out(n, k, 2), &
2422 w%r(k, k, 2), w%sinp(k, k, 2), w%buf1(k, k, 2), w%buf2(k, k, 2), &
2423 w%buf3(k, k, 2), w%buf4(k, k, 2), w%buf_nk(n, k, 2), &
2424 w%sinp_b(k, k), w%cosp_b(k, k), w%tmp(n, k))
2427 END SUBROUTINE qs_ot_allocate_local_work
2435 SUBROUTINE qs_ot_store_local_pair(matrix_re, matrix_im, dense)
2436 TYPE(
dbcsr_type),
INTENT(INOUT) :: matrix_re, matrix_im
2437 REAL(
dp),
INTENT(IN) :: dense(:, :, :)
2441 END SUBROUTINE qs_ot_store_local_pair
2454 matrix_hc_physical, matrix_hc_physical_im)
2455 TYPE(
qs_ot_type),
INTENT(INOUT) :: qs_ot_env(:)
2456 TYPE(
dbcsr_p_type),
INTENT(IN) :: matrix_hc(:), matrix_hc_im(:)
2457 LOGICAL,
INTENT(OUT) :: handled
2458 TYPE(
dbcsr_p_type),
INTENT(IN),
OPTIONAL :: matrix_hc_physical(:), &
2459 matrix_hc_physical_im(:)
2461 CHARACTER(LEN=*),
PARAMETER :: routinen =
'qs_ot_get_derivative_local_batch'
2463 INTEGER :: first, handle, i, j, nbatch, nchannels, &
2464 npasses, nworkers, pass
2466 TYPE(qs_ot_local_work_type),
ALLOCATABLE :: work(:)
2469 IF (.NOT. qs_ot_local_channels(qs_ot_env))
RETURN
2470 ref = qs_ot_env(1)%settings%ot_algorithm ==
'REF'
2472 IF (
PRESENT(matrix_hc_physical))
THEN
2473 IF (.NOT. ref)
RETURN
2474 cpassert(
PRESENT(matrix_hc_physical_im))
2477 nchannels =
SIZE(qs_ot_env)
2479 CALL timeset(routinen, handle)
2482 ALLOCATE (work(nworkers))
2486 DO first = 1, nchannels, nworkers
2487 nbatch = min(nworkers, nchannels - first + 1)
2491 CALL qs_ot_load_local_work(work(j), qs_ot_env(i), matrix_hc(i)%matrix, matrix_hc_im(i)%matrix)
2492 work(j)%filtered = ref .AND. qs_ot_env(i)%settings%eps_irac_filter_matrix > 0.0_dp
2494 DO pass = 1, npasses
2498 CALL qs_ot_load_local_pair(matrix_hc_physical(i)%matrix, matrix_hc_physical_im(i)%matrix, work(j)%hc)
2505 CALL qs_ot_complex_multiply_local(
'N',
'N', work(j)%x, work(j)%sinp, &
2506 work(j)%c0, work(j)%tmp, work(j)%gemm_ctx)
2507 CALL qs_ot_complex_multiply_local(
'C',
'N', work(j)%c0, work(j)%hc, &
2508 work(j)%buf3, work(j)%buf2(:, :, 1), work(j)%gemm_ctx)
2509 IF (.NOT. work(j)%filtered)
CALL qs_ot_ref_gradient_local(work(j))
2511 CALL qs_ot_strict_gradient_local(work(j))
2515 IF (any(work(1:nbatch)%filtered))
THEN
2518 IF (.NOT. work(j)%filtered) cycle
2520 CALL qs_ot_store_local_pair(qs_ot_env(i)%buf1_k_k_sym, qs_ot_env(i)%buf2_k_k_sym, work(j)%buf3)
2521 CALL dbcsr_filter(qs_ot_env(i)%buf1_k_k_sym, qs_ot_env(i)%settings%eps_irac_filter_matrix)
2522 CALL dbcsr_filter(qs_ot_env(i)%buf2_k_k_sym, qs_ot_env(i)%settings%eps_irac_filter_matrix)
2523 CALL qs_ot_load_local_pair(qs_ot_env(i)%buf1_k_k_sym, qs_ot_env(i)%buf2_k_k_sym, work(j)%buf3)
2527 IF (work(j)%filtered)
CALL qs_ot_ref_gradient_local(work(j))
2533 CALL qs_ot_store_local_pair(qs_ot_env(i)%matrix_gx, qs_ot_env(i)%matrix_gx_im, work(j)%out)
2534 IF (work(j)%filtered)
THEN
2535 CALL dbcsr_filter(qs_ot_env(i)%matrix_gx, qs_ot_env(i)%settings%eps_irac_filter_matrix)
2536 CALL dbcsr_filter(qs_ot_env(i)%matrix_gx_im, qs_ot_env(i)%settings%eps_irac_filter_matrix)
2538 IF (pass < npasses)
THEN
2539 CALL dbcsr_copy(qs_ot_env(i)%matrix_preconditioned_gx, qs_ot_env(i)%matrix_gx)
2540 CALL dbcsr_copy(qs_ot_env(i)%matrix_preconditioned_gx_im, qs_ot_env(i)%matrix_gx_im)
2546 CALL work(j)%gemm_ctx%destroy()
2549 CALL timestop(handle)
2556 SUBROUTINE qs_ot_ref_gradient_local(w)
2557 TYPE(qs_ot_local_work_type),
INTENT(INOUT) :: w
2559 CALL qs_ot_complex_multiply_local(
'N',
'N', w%sx, w%sinp, w%buf_nk, w%tmp, w%gemm_ctx)
2560 CALL qs_ot_complex_multiply_local(
'N',
'N', w%buf_nk, w%buf3, w%c0, w%tmp, w%gemm_ctx)
2561 w%c0(:, :, :) = w%hc(:, :, :) - w%c0(:, :, :)
2562 CALL qs_ot_complex_multiply_local(
'N',
'N', w%c0, w%sinp, w%out, w%tmp, w%gemm_ctx)
2563 END SUBROUTINE qs_ot_ref_gradient_local
2576 SUBROUTINE qs_ot_strict_frechet(matrix_hc, matrix_hc_im, orbital, orbital_im, kernel, &
2577 RESULT, result_im, qs_ot_env)
2579 orbital_im, kernel, result, result_im
2583 qs_ot_env%matrix_buf2, qs_ot_env%matrix_buf2_im, qs_ot_env%matrix_buf1)
2585 qs_ot_env%matrix_r, qs_ot_env%matrix_r_im, &
2586 qs_ot_env%matrix_buf1, qs_ot_env%matrix_buf1_im, qs_ot_env%matrix_buf4)
2588 qs_ot_env%matrix_buf1, qs_ot_env%matrix_buf1_im, &
2589 qs_ot_env%matrix_buf2, qs_ot_env%matrix_buf2_im, qs_ot_env%matrix_buf4)
2592 END SUBROUTINE qs_ot_strict_frechet
2601 SUBROUTINE qs_ot_load_local_work(w, qs_ot_env, matrix_hc, matrix_hc_im)
2602 TYPE(qs_ot_local_work_type),
INTENT(INOUT) :: w
2604 TYPE(
dbcsr_type),
INTENT(IN) :: matrix_hc, matrix_hc_im
2608 CALL dbcsr_get_info(qs_ot_env%matrix_x, nfullrows_total=n, nfullcols_total=k)
2609 CALL qs_ot_allocate_local_work(w, n, k)
2610 IF (
ALLOCATED(w%hc))
THEN
2611 IF (
SIZE(w%hc, 1) /= n .OR.
SIZE(w%hc, 2) /= k)
DEALLOCATE (w%hc)
2613 IF (.NOT.
ALLOCATED(w%hc))
ALLOCATE (w%hc(n, k, 2))
2614 CALL qs_ot_load_local_pair(matrix_hc, matrix_hc_im, w%hc)
2615 CALL qs_ot_load_local_pair(qs_ot_env%matrix_x, qs_ot_env%matrix_x_im, w%x)
2616 CALL qs_ot_load_local_pair(qs_ot_env%matrix_sx, qs_ot_env%matrix_sx_im, w%sx)
2617 IF (qs_ot_env%settings%ot_algorithm ==
'REF')
THEN
2618 CALL qs_ot_load_local_pair(qs_ot_env%matrix_ref_inv_sqrt, qs_ot_env%matrix_ref_inv_sqrt_im, w%sinp)
2622 IF (
ALLOCATED(w%sc0))
THEN
2623 IF (
SIZE(w%sc0, 1) /= n .OR.
SIZE(w%buf1_ortho, 2) /= k .OR. o /=
SIZE(w%sc0, 2))
THEN
2624 DEALLOCATE (w%sc0, w%target, w%os, w%buf1_ortho, w%buf2_ortho, w%tmp_ortho)
2627 IF (.NOT.
ALLOCATED(w%sc0))
THEN
2628 ALLOCATE (w%sc0(n, o, 2), w%target(n, o, 2), w%os(o, o, 2), &
2629 w%buf1_ortho(o, k, 2), w%buf2_ortho(o, k, 2), w%tmp_ortho(o, k))
2631 CALL qs_ot_load_local_pair(qs_ot_env%matrix_c0, qs_ot_env%matrix_c0_im, w%c0)
2632 CALL qs_ot_load_local_pair(qs_ot_env%matrix_r, qs_ot_env%matrix_r_im, w%r)
2633 CALL qs_ot_load_local_pair(qs_ot_env%matrix_sinp, qs_ot_env%matrix_sinp_im, w%sinp)
2634 CALL qs_ot_load_local_pair(qs_ot_env%matrix_sc0, qs_ot_env%matrix_sc0_im, w%sc0)
2635 CALL qs_ot_load_local_pair(qs_ot_env%matrix_os, qs_ot_env%matrix_os_im, w%os)
2638 IF (
ASSOCIATED(qs_ot_env%preconditioner))
THEN
2639 CALL qs_ot_load_local_pair(qs_ot_env%matrix_psc0, qs_ot_env%matrix_psc0_im, w%target)
2641 w%target(:, :, :) = w%sc0(:, :, :)
2643 END SUBROUTINE qs_ot_load_local_work
2651 SUBROUTINE qs_ot_load_local_pair(matrix_re, matrix_im, dense)
2652 TYPE(
dbcsr_type),
INTENT(IN) :: matrix_re, matrix_im
2653 REAL(
dp),
INTENT(OUT) :: dense(:, :, :)
2657 END SUBROUTINE qs_ot_load_local_pair
2669 SUBROUTINE qs_ot_complex_multiply_pair_local(op_a, op_b, a, b, c, tmp, gemm_ctx)
2670 CHARACTER(LEN=1),
INTENT(IN) :: op_a, op_b
2671 REAL(
dp),
CONTIGUOUS,
INTENT(IN) :: a(:, :, :), b(:, :, :)
2672 REAL(
dp),
CONTIGUOUS,
INTENT(INOUT) :: c(:, :, :), tmp(:, :)
2675 CALL qs_ot_complex_multiply_parts_local(op_a, op_b, a(:, :, 1), a(:, :, 2), &
2676 b(:, :, 1), b(:, :, 2), c(:, :, 1), c(:, :, 2), tmp, gemm_ctx)
2677 END SUBROUTINE qs_ot_complex_multiply_pair_local
2692 SUBROUTINE qs_ot_complex_multiply_parts_local(op_a, op_b, a_re, a_im, b_re, b_im, &
2693 c_re, c_im, tmp, gemm_ctx)
2694 CHARACTER(LEN=1),
INTENT(IN) :: op_a, op_b
2695 REAL(
dp),
CONTIGUOUS,
INTENT(IN) :: a_re(:, :), a_im(:, :), b_re(:, :), &
2697 REAL(
dp),
CONTIGUOUS,
INTENT(INOUT) :: c_re(:, :), c_im(:, :), tmp(:, :)
2700 CHARACTER(LEN=1) :: trans_a, trans_b
2702 REAL(
dp) :: sign_a, sign_b
2704 cpassert(op_a ==
'N' .OR. op_a ==
'C')
2705 cpassert(op_b ==
'N' .OR. op_b ==
'C')
2706 trans_a = merge(
'N',
'T', op_a ==
'N')
2707 trans_b = merge(
'N',
'T', op_b ==
'N')
2708 sign_a = merge(1.0_dp, -1.0_dp, op_a ==
'N')
2709 sign_b = merge(1.0_dp, -1.0_dp, op_b ==
'N')
2712 k = merge(
SIZE(a_re, 2),
SIZE(a_re, 1), op_a ==
'N')
2713 CALL gemm_ctx%gemm(trans_a, trans_b, m, n, k, 1.0_dp, a_re,
SIZE(a_re, 1), &
2714 b_re,
SIZE(b_re, 1), 0.0_dp, c_re,
SIZE(c_re, 1))
2715 CALL gemm_ctx%gemm(trans_a, trans_b, m, n, k, 1.0_dp, a_im,
SIZE(a_im, 1), &
2716 b_im,
SIZE(b_im, 1), 0.0_dp, tmp,
SIZE(tmp, 1))
2717 c_re(:, :) = c_re(:, :) - sign_a*sign_b*tmp(1:m, 1:n)
2718 CALL gemm_ctx%gemm(trans_a, trans_b, m, n, k, sign_b, a_re,
SIZE(a_re, 1), &
2719 b_im,
SIZE(b_im, 1), 0.0_dp, c_im,
SIZE(c_im, 1))
2720 CALL gemm_ctx%gemm(trans_a, trans_b, m, n, k, sign_a, a_im,
SIZE(a_im, 1), &
2721 b_re,
SIZE(b_re, 1), 0.0_dp, tmp,
SIZE(tmp, 1))
2722 c_im(:, :) = c_im(:, :) + tmp(1:m, 1:n)
2723 END SUBROUTINE qs_ot_complex_multiply_parts_local
2732 SUBROUTINE qs_ot_strict_frechet_local(w, orbital, kernel, RESULT)
2733 TYPE(qs_ot_local_work_type) :: w
2734 REAL(
dp),
CONTIGUOUS,
INTENT(IN) ::
orbital(:, :, :), kernel(:, :)
2735 REAL(
dp),
CONTIGUOUS,
INTENT(INOUT) :: result(:, :, :)
2737 CALL qs_ot_complex_multiply_local(
'C',
'N', w%hc,
orbital, w%buf2, w%buf1(:, :, 1), w%gemm_ctx)
2738 CALL qs_ot_complex_multiply_local(
'N',
'N', w%buf2, w%r, w%buf1, w%buf4(:, :, 1), w%gemm_ctx)
2739 CALL qs_ot_complex_multiply_local(
'C',
'N', w%r, w%buf1, w%buf2, w%buf4(:, :, 1), w%gemm_ctx)
2740 result(:, :, 1) = w%buf2(:, :, 1)*kernel(:, :)
2741 result(:, :, 2) = w%buf2(:, :, 2)*kernel(:, :)
2742 END SUBROUTINE qs_ot_strict_frechet_local
2748 SUBROUTINE qs_ot_strict_gradient_local(w)
2749 TYPE(qs_ot_local_work_type) :: w
2755 CALL qs_ot_complex_multiply_local(
'N',
'N', w%hc, w%sinp, w%out, w%tmp, w%gemm_ctx)
2756 CALL qs_ot_strict_frechet_local(w, w%x, w%sinp_b, w%buf3)
2757 CALL qs_ot_strict_frechet_local(w, w%c0, w%cosp_b, w%buf4)
2758 w%buf3(:, :, :) = w%buf3(:, :, :) + w%buf4(:, :, :)
2759 CALL qs_ot_complex_multiply_local(
'N',
'N', w%r, w%buf3, w%buf1, w%buf2(:, :, 1), w%gemm_ctx)
2760 CALL qs_ot_complex_multiply_local(
'N',
'C', w%buf1, w%r, w%buf3, w%buf2(:, :, 1), w%gemm_ctx)
2764 w%buf3(j, j, 1) = w%buf3(j, j, 1) + w%buf3(j, j, 1)
2765 w%buf3(j, j, 2) = 0.0_dp
2767 re = w%buf3(i, j, 1) + w%buf3(j, i, 1)
2768 im = w%buf3(i, j, 2) - w%buf3(j, i, 2)
2769 w%buf3(i, j, 1) = re
2770 w%buf3(j, i, 1) = re
2771 w%buf3(i, j, 2) = im
2772 w%buf3(j, i, 2) = -im
2775 CALL qs_ot_complex_multiply_local(
'N',
'N', w%sx, w%buf3, w%buf_nk, w%tmp, w%gemm_ctx)
2776 w%out(:, :, :) = w%out(:, :, :) + w%buf_nk(:, :, :)
2779 CALL qs_ot_complex_multiply_local(
'C',
'N', w%target, w%out, w%buf1_ortho, w%tmp_ortho, w%gemm_ctx)
2780 CALL qs_ot_complex_multiply_local(
'N',
'N', w%os, w%buf1_ortho, w%buf2_ortho, w%tmp_ortho, w%gemm_ctx)
2781 CALL qs_ot_complex_multiply_local(
'N',
'N', w%sc0, w%buf2_ortho, w%buf_nk, w%tmp, w%gemm_ctx)
2782 w%out(:, :, :) = w%out(:, :, :) - w%buf_nk(:, :, :)
2783 END SUBROUTINE qs_ot_strict_gradient_local
used for collecting diagonalization schemes available for cp_cfm_type
subroutine, public cp_cfm_heevd_local(matrix, vectors, info, ws)
Local LAPACK ZHEEVD with prepared scratch, without allocation or communication.
subroutine, public cp_cfm_local_workspace_prepare(ws, n, a, b)
Query LAPACK once per matrix order/solver and retain private scratch across k points.
Represents a complex full matrix distributed on many processors.
subroutine, public dbcsr_transposed(transposed, normal, shallow_data_copy, transpose_distribution, use_distribution)
...
subroutine, public dbcsr_scale(matrix, alpha_scalar)
...
logical function, public dbcsr_iterator_blocks_left(iterator)
...
subroutine, public dbcsr_iterator_stop(iterator)
...
subroutine, public dbcsr_copy(matrix_b, matrix_a, name, keep_sparsity, keep_imaginary)
...
subroutine, public dbcsr_get_block_p(matrix, row, col, block, found, row_size, col_size)
...
subroutine, public dbcsr_multiply(transa, transb, alpha, matrix_a, matrix_b, beta, matrix_c, first_row, last_row, first_column, last_column, first_k, last_k, retain_sparsity, filter_eps, flop)
...
subroutine, public dbcsr_get_info(matrix, nblkrows_total, nblkcols_total, nfullrows_total, nfullcols_total, nblkrows_local, nblkcols_local, nfullrows_local, nfullcols_local, my_prow, my_pcol, local_rows, local_cols, proc_row_dist, proc_col_dist, row_blk_size, col_blk_size, row_blk_offset, col_blk_offset, distribution, name, matrix_type, group)
...
subroutine, public dbcsr_reserve_blocks(matrix, rows, cols)
...
subroutine, public dbcsr_iterator_next_block(iterator, row, column, block, block_number_argument_has_been_removed, row_size, col_size, row_offset, col_offset, transposed)
...
subroutine, public dbcsr_filter(matrix, eps)
...
subroutine, public dbcsr_finalize(matrix)
...
subroutine, public dbcsr_iterator_start(iterator, matrix, shared, dynamic, dynamic_byrows)
...
subroutine, public dbcsr_set(matrix, alpha)
...
subroutine, public dbcsr_release(matrix)
...
subroutine, public dbcsr_add(matrix_a, matrix_b, alpha_scalar, beta_scalar)
...
subroutine, public dbcsr_add_on_diag(matrix, alpha)
Adds the given scalar to the diagonal of the matrix. Reserves any missing diagonal blocks.
subroutine, public dbcsr_reserve_all_blocks(matrix)
Reserves all blocks.
real(dp) function, public dbcsr_frobenius_norm(matrix)
Compute the frobenius norm of a dbcsr matrix.
subroutine, public dbcsr_hadamard_product(matrix_a, matrix_b, matrix_c)
Hadamard product: C = A . B (C needs to be different from A and B).
subroutine, public dbcsr_scale_by_vector(matrix, alpha, side)
Scales the rows/columns of given matrix.
Interface to (sca)lapack for the Cholesky based procedures.
subroutine, public cp_dbcsr_heevd(matrix_re, matrix_im, eigenvectors_re, eigenvectors_im, eigenvalues, para_env, blacs_env)
...
DBCSR operations in CP2K.
subroutine, public copy_local_to_dbcsr(matrix, dense)
Store a single-rank, nonsymmetric matrix without redistribution.
subroutine, public copy_dbcsr_to_local(matrix, dense)
Load a single-rank, nonsymmetric matrix without redistribution.
used for collecting some of the diagonalization schemes available for cp_fm_type. cp_fm_power also mo...
integer, parameter, public fm_diag_type_dlaf
integer, save, public diag_type
logical, save, public diag_lib_explicit
represent a full matrix distributed on many processors
Defines the basic variable types.
integer, parameter, public dp
integer, parameter, public local_gemm_pu_gpu
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.
subroutine, public diamat_all(a, eigval, dac)
Diagonalize the symmetric n by n matrix a using the LAPACK library. Only the upper triangle of matrix...
computes preconditioners, and implements methods to apply them currently used in qs_ot
Complex k-point orbital transformations, response kernels and local batch execution....
subroutine, public qs_ot_rot_mat_derivative_complex(qs_ot_env)
pull the complex dE/dU covector back to the anti-Hermitian generator using the adjoint Frechet deriva...
subroutine, public qs_ot_get_derivative_local_batch(qs_ot_env, matrix_hc, matrix_hc_im, handled, matrix_hc_physical, matrix_hc_physical_im)
Evaluate independent, single-rank STRICT/IRAC gradients in bounded OpenMP batches....
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_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_get_orbitals_local_batch(qs_ot_env, matrix_s, matrix_c, handled, initialize)
Rebuild single-rank STRICT/IRAC orbitals in bounded batches using cached overlaps....
pure real(kind=dp) function, public qs_ot_fixed_n_response_mu_shift(weighted_energy_response, local_curvature_sum, fixed_n_curvature_sum)
chemical-potential response for one fixed-electron-number group
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_prepare_complex_tangent_metric_batch(qs_ot_env)
Prepare uncached single-rank STRICT metrics in bounded OpenMP batches. Leave unsuccessful channels to...
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
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
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_prepare_complex_tangent_metric(qs_ot_env, preconditioner_rejected, use_preconditioner)
Prepare the inverse metric used to project a complex STRICT gradient. An unusable preconditioner is d...
subroutine, public qs_ot_get_p_complex(matrix_x, matrix_x_im, matrix_sx, matrix_sx_im, qs_ot_env, zero_coordinates)
compute P=X^H*S*X and the STRICT matrix functions for a complex K-point channel
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
subroutine, public qs_ot_generate_rotation_complex(qs_ot_env)
computes U=exp(A) for the complex anti-Hermitian generator A=rot_mat_x+i*rot_mat_x_im
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 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_get_orbitals_complex(matrix_c, matrix_c_im, matrix_s, matrix_s_im, qs_ot_env)
update complex K-point orbitals with the finite STRICT transformation
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
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_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
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_complex_multiply(op_a, op_b, a_re, a_im, b_re, b_im, c_re, c_im, tmp)
multiply paired real/imaginary DBCSR matrices, with optional conjugate transposes
logical function, public qs_ot_ref_update(qs_ot_env1)
...
subroutine, public qs_ot_spectral_kernel(roots_i, roots_j, block, cosine)
Build a block of the real STRICT Frechet kernel, including coincident eigenvalues.
subroutine, public qs_ot_spectral_values(evals, values, cosine)
Evaluate cos(sqrt(P)) or sinc(sqrt(P)) on the nonnegative eigenvalues of P.
subroutine, public qs_ot_square_transpose(matrix, transposed, identity_template)
Transpose a square DBCSR matrix while retaining its target distribution.
subroutine, public qs_ot_p2m_diag(qs_ot_env)
given p, computes - eigenstuff (matrix_r,evals)
subroutine, public qs_ot_project_gradient(qs_ot_env, matrix_gx, use_preconditioner)
Project a real STRICT gradient, or an identity-metric fallback direction.
Just to build arrays of pointers to matrices.
just to build arrays of pointers to matrices
Orbital angular momentum.