34 use,
intrinsic :: iso_fortran_env
64 integer,
public,
parameter :: &
71 integer,
public :: exp_method
72 real(real64) :: lanczos_tol
73 real(real64) :: chebyshev_tol
74 integer,
public :: exp_order
76 logical,
public :: full_batch = .false.
85 type(namespace_t),
pointer :: namespace
86 class(mesh_t),
pointer :: mesh
88 procedure(operator_apply),
deferred :: apply
95 class(operator_t),
intent(in) :: this
96 class(batch_t),
intent(inout) :: psib
97 class(batch_t),
intent(inout) :: hpsib
103 class(hamiltonian_abst_t),
pointer :: hm
110 procedure hamiltonian_operator_constructor
117 type(exponential_t),
intent(out) :: te
118 type(namespace_t),
intent(in) :: namespace
119 logical,
optional,
intent(in) :: full_batch
178 select case (te%exp_method)
191 call parse_variable(namespace,
'TDChebyshevTol', 1e-10_real64, te%chebyshev_tol)
205 call parse_variable(namespace,
'TDLanczosTol', 1e-6_real64, te%lanczos_tol)
222 call parse_variable(namespace,
'TDExpOrder', default__tdexporder, te%exp_order)
226 message(1) =
"TDExpOrder is only relevant for TDExponentialMethod = taylor"
231 te%arnoldi_gs = option__arnoldiorthogonalization__cgs
232 if (te%exp_method == exp_lanczos)
then
247 call parse_variable(namespace,
'ArnoldiOrthogonalization', option__arnoldiorthogonalization__cgs, &
264 teo%exp_method = tei%exp_method
265 teo%lanczos_tol = tei%lanczos_tol
266 teo%exp_order = tei%exp_order
267 teo%arnoldi_gs = tei%arnoldi_gs
277 class(
mesh_t),
intent(in) :: mesh
279 integer,
intent(in) :: ist
280 integer,
intent(in) :: ik
281 complex(real64),
contiguous,
intent(inout) :: zpsi(:, :)
282 real(real64),
intent(in) :: deltat
283 logical,
optional,
intent(in) :: imag_time
286 complex(real64),
allocatable :: zpsi_inh(:, :)
292 if (hm%phase%is_allocated())
then
293 call hm%phase%apply_to_single(zpsi, mesh%np, hm%d%dim, ik, .false.)
299 safe_allocate(zpsi_inh(1:mesh%np_part, 1:hm%d%dim))
301 call wfs_elec_init(inh_psib, hm%d%dim, ist, ist, zpsi_inh, ik)
302 call te%apply_batch(namespace, mesh, hm, psib, deltat, &
303 imag_time=imag_time, inh_psib=inh_psib)
305 safe_deallocate_a(zpsi_inh)
307 call te%apply_batch(namespace, mesh, hm, psib, deltat, &
313 if (hm%phase%is_allocated())
then
314 call hm%phase%apply_to_single(zpsi, mesh%np, hm%d%dim, ik, .
true.)
338 subroutine exponential_apply_batch(te, namespace, mesh, hm, psib, deltat, psib2, deltat2, imag_time, inh_psib, op)
341 class(
mesh_t),
intent(in) :: mesh
343 class(
batch_t),
intent(inout) :: psib
344 real(real64),
intent(in) :: deltat
345 class(
batch_t),
optional,
intent(inout) :: psib2
346 real(real64),
optional,
intent(in) :: deltat2
347 logical,
optional,
intent(in) :: imag_time
348 class(
batch_t),
optional,
intent(inout) :: inh_psib
349 class(
operator_t),
target,
optional,
intent(in) :: op
351 complex(real64) :: deltat_, deltat2_
353 logical :: imag_time_
361 assert(
present(psib2) .eqv.
present(deltat2))
362 if (
present(inh_psib))
then
363 assert(inh_psib%nst == psib%nst)
366 if (
present(op))
then
376 deltat_ = -
m_zi*deltat
377 if (
present(deltat2)) deltat2_ =
m_zi*deltat2
379 deltat_ = cmplx(deltat,
m_zero, real64)
380 if (
present(deltat2)) deltat2_ = cmplx(deltat2,
m_zero, real64)
383 if (.not. hm%is_hermitian() .and. te%exp_method ==
exp_chebyshev)
then
384 write(
message(1),
'(a)')
'The Chebyshev expansion cannot be used for non-Hermitian operators.'
385 write(
message(2),
'(a)')
'Please use the Lanczos exponentiation scheme ("TDExponentialMethod = lanczos")'
386 write(
message(3),
'(a)')
'or the Taylor expansion ("TDExponentialMethod = taylor") method.'
390 select case (te%exp_method)
393 if (
present(deltat2))
then
399 if (
present(inh_psib))
then
400 if (
present(deltat2))
then
402 psib2, deltat2_, inh_psib)
410 if (
present(psib2))
call psib%copy_data_to(mesh%np, psib2)
412 if (
present(inh_psib))
then
415 if (
present(psib2))
then
417 if (
present(inh_psib))
then
423 if (
present(inh_psib))
then
424 write(
message(1),
'(a)')
'Chebyshev exponential ("TDExponentialMethod = chebyshev")'
425 write(
message(2),
'(a)')
'with inhomogeneous term is not implemented'
431 if (
present(psib2))
then
435 chebyshev_function =>
chebyshev_exp_t(hm%spectral_half_span, hm%spectral_middle_point, deltat)
436 if (
present(psib2))
then
437 chebyshev_function_dt2 =>
chebyshev_exp_t(hm%spectral_half_span, hm%spectral_middle_point, deltat2)
440 if (
present(psib2))
call psib%copy_data_to(mesh%np, psib2)
442 deallocate(chebyshev_function)
443 if (
present(psib2))
then
445 deallocate(chebyshev_function_dt2)
450 if (.not.
present(op))
then
451 safe_deallocate_p(op_)
459 subroutine exponential_taylor_series_batch(te, namespace, mesh, hm, psib, deltat, op, psib2, deltat2, inh_psib, phik_shift)
462 class(
mesh_t),
intent(in) :: mesh
464 class(
batch_t),
intent(inout) :: psib
465 complex(real64),
intent(in) :: deltat
467 class(
batch_t),
optional,
intent(inout) :: psib2
468 complex(real64),
optional,
intent(in) :: deltat2
469 class(
batch_t),
optional,
intent(inout) :: inh_psib
470 integer,
optional,
intent(in) :: phik_shift
472 complex(real64) :: zfact, zfact2
473 integer :: iter, denom, phik_shift_
474 logical :: zfact_is_real
475 class(
batch_t),
allocatable :: psi1b, hpsi1b
480 call psib%clone_to(psi1b)
481 call psib%clone_to(hpsi1b)
485 zfact_is_real = abs(deltat-real(deltat, real64)) <
m_epsilon
487 if (
present(psib2))
call psib%copy_data_to(mesh%np, psib2)
489 if (
present(inh_psib))
then
491 call batch_axpy(mesh%np, real(zfact, real64), inh_psib, psib)
493 if (
present(psib2))
then
494 zfact2 = zfact2*deltat2
495 call batch_axpy(mesh%np, real(zfact2, real64), inh_psib, psib2)
502 do iter = 1, te%exp_order
503 denom = iter+phik_shift_
504 if (
present(inh_psib)) denom = denom + 1
505 zfact = zfact*(-
m_zi*deltat)/denom
506 if (
present(deltat2)) zfact2 = zfact2*(-
m_zi*deltat2)/denom
507 zfact_is_real = .not. zfact_is_real
514 call op%apply(psi1b, hpsi1b)
516 if (
present(inh_psib))
then
517 call op%apply(inh_psib, hpsi1b)
519 call op%apply(psib, hpsi1b)
523 if (zfact_is_real)
then
524 call batch_axpy(mesh%np, real(zfact, real64), hpsi1b, psib)
525 if (
present(psib2))
call batch_axpy(mesh%np, real(zfact2, real64), hpsi1b, psib2)
528 if (
present(psib2))
call batch_axpy(mesh%np, zfact2, hpsi1b, psib2)
531 if (iter /= te%exp_order)
call hpsi1b%copy_data_to(mesh%np, psi1b)
537 safe_deallocate_a(psi1b)
538 safe_deallocate_a(hpsi1b)
547 class(
mesh_t),
intent(in) :: mesh
549 class(
batch_t),
intent(inout) :: psib
550 complex(real64),
intent(in) :: deltat
552 class(
batch_t),
optional,
intent(in) :: inh_psib
558 if (
present(inh_psib))
then
559 call inh_psib%clone_to(tmpb, copy_data=.
true.)
562 call batch_axpy(mesh%np, real(deltat, real64), tmpb, psib)
564 safe_deallocate_a(tmpb)
587 class(
mesh_t),
intent(in) :: mesh
589 class(
batch_t),
intent(inout) :: psib
590 complex(real64),
intent(in) :: deltat
592 complex(real64) function fun(z)
594 complex(real64),
intent(in) :: z
599 integer :: iter, l, ii, ist, max_initialized
600 complex(real64),
allocatable :: hamilt(:,:,:), expo(:,:,:)
601 real(real64),
allocatable :: beta(:), res(:), norm(:)
602 integer,
parameter :: max_order = 200
608 if (te%exp_method /= exp_lanczos)
then
609 message(1) =
"The exponential method needs to be set to Lanzcos (TDExponentialMethod=lanczos)."
613 safe_allocate(beta(1:psib%nst))
614 safe_allocate(res(1:psib%nst))
615 safe_allocate(norm(1:psib%nst))
616 safe_allocate(vb(1:max_order))
617 call psib%clone_to(vb(1)%p)
620 call psib%copy_data_to(mesh%np, vb(1)%p, async=.
true.)
623 if (te%full_batch) beta = norm2(beta)
626 if (all(abs(beta) <= 1.0e-12_real64))
then
627 safe_deallocate_a(beta)
628 safe_deallocate_a(res)
629 safe_deallocate_a(norm)
631 safe_deallocate_a(vb)
639 safe_allocate(hamilt(1:max_order+1, 1:max_order+1, 1:psib%nst))
640 safe_allocate( expo(1:max_order+1, 1:max_order+1, 1:psib%nst))
643 do iter = 1, max_order-1
644 call psib%clone_to(vb(iter + 1)%p)
645 max_initialized = iter + 1
648 call op%apply(vb(iter)%p, vb(iter+1)%p)
651 if (hm%is_hermitian())
then
653 hamilt(1:max(l-1, 1), iter, 1:psib%nst) =
m_zero
657 hamilt(iter, 1:iter-2, 1:psib%nst) =
m_zero
663 normalize = .false., overlap = hamilt(l:iter, iter, 1:psib%nst), norm = hamilt(iter + 1, iter, 1:psib%nst), &
664 gs_scheme = te%arnoldi_gs, full_batch = te%full_batch)
674 hm%is_hermitian(), tridiagonal=hm%is_hermitian())
675 res(ii) = abs(hamilt(iter + 1, iter, ii) * abs(expo(iter, 1, ii)))
679 if (all(abs(hamilt(iter + 1, iter, :)) < 1.0e4_real64*
m_epsilon))
exit
684 if (abs(hamilt(iter + 1, iter, ist)) >= 1.0e4_real64 *
m_epsilon)
then
685 norm(ist) =
m_one / abs(hamilt(iter + 1, iter, ist))
689 call batch_scal(mesh%np, norm, vb(iter+1)%p, a_full = .false.)
691 if (iter > 3 .and. all(res < te%lanczos_tol))
exit
695 if (iter == max_order)
then
696 write(
message(1),
'(a,i5,a,es9.2)')
'Lanczos exponential expansion did not converge after ', iter, &
697 ' iterations. Residual: ', maxval(res)
700 write(
message(1),
'(a,i5)')
'Debug: Lanczos exponential iterations: ', iter
706 call batch_scal(mesh%np, expo(1,1,1:psib%nst), psib, a_full = .false.)
709 call batch_axpy(mesh%np, beta(1:psib%nst)*expo(ii,1,1:psib%nst), vb(ii)%p, psib, a_full = .false.)
714 do ii = 1, max_initialized
718 safe_deallocate_a(vb)
719 safe_deallocate_a(hamilt)
720 safe_deallocate_a(expo)
721 safe_deallocate_a(beta)
722 safe_deallocate_a(res)
723 safe_deallocate_a(norm)
748 class(
mesh_t),
intent(in) :: mesh
750 class(
batch_t),
intent(inout) :: psib
754 integer :: j, order_needed
755 complex(real64) :: coefficient
756 complex(real64),
allocatable :: coefficients(:)
757 real(real64) :: error
758 class(
batch_t),
allocatable,
target :: psi0, psi1, psi2
759 class(
batch_t),
pointer :: psi_n, psi_n1, psi_n2
760 integer,
parameter :: max_order = 200
765 call psib%clone_to(psi0)
766 call psib%clone_to(psi1)
767 call psib%clone_to(psi2)
768 call psib%copy_data_to(mesh%np, psi0)
770 order_needed = max_order
772 error = chebyshev_function%get_error(j)
773 if (error >
m_zero .and. error < te%chebyshev_tol)
then
779 call chebyshev_function%get_coefficients(j, coefficients)
782 call batch_scal(mesh%np, coefficients(0), psib)
785 call op%apply(psi0, psi1)
786 call batch_axpy(mesh%np, -hm%spectral_middle_point, psi0, psi1)
789 call batch_axpy(mesh%np, coefficients(1), psi1, psib)
796 do j = 2, order_needed
798 call op%apply(psi_n1, psi_n)
799 call batch_axpy(mesh%np, -hm%spectral_middle_point, psi_n1, psi_n)
804 call batch_axpy(mesh%np, coefficients(j), psi_n, psib)
807 if (mod(j, 3) == 2)
then
811 else if (mod(j, 3) == 1)
then
822 if (order_needed == max_order)
then
823 write(
message(1),
'(a,i5,a,es9.2)')
'Chebyshev exponential expansion did not converge after ', j, &
824 ' iterations. Coefficient: ', coefficient
827 write(
message(1),
'(a,i5)')
'Debug: Chebyshev exponential iterations: ', j
834 safe_deallocate_a(psi0)
835 safe_deallocate_a(psi1)
836 safe_deallocate_a(psi2)
838 safe_deallocate_a(coefficients)
852 type(
grid_t),
intent(inout) :: gr
855 real(real64),
intent(in) :: deltat
856 integer,
optional,
intent(inout) :: order
859 real(real64) :: zfact
871 do i = 1, te%exp_order
872 zfact = zfact * deltat / i
880 do ik = st%d%kpt%start, st%d%kpt%end
881 do ib = st%group%block_start, st%group%block_end
882 call batch_scal2v(gr%np, -
m_zi, hst1%group%psib(ib, ik), st1%group%psib(ib, ik), conjugate_xx = .false.)
883 call batch_axpy(gr%np, zfact, st1%group%psib(ib, ik), st%group%psib(ib, ik))
901 do ik = st%d%kpt%start, st%d%kpt%end
902 do ib = st%group%block_start, st%group%block_end
903 call batch_axpy(gr%np, deltat, st1%group%psib(ib, ik), st%group%psib(ib, ik))
908 do i = 1, te%exp_order
909 zfact = zfact * deltat / (i+1)
917 do ik = st%d%kpt%start, st%d%kpt%end
918 do ib = st%group%block_start, st%group%block_end
919 call batch_scal2v(gr%np, -
m_zi, hst1%group%psib(ib, ik), st1%group%psib(ib, ik), conjugate_xx = .false.)
920 call batch_axpy(gr%np, deltat * zfact, st1%group%psib(ib, ik), st%group%psib(ib, ik))
931 if (
present(order)) order = te%exp_order*st%nik*st%nst
939 class(
mesh_t),
intent(in) :: mesh
941 class(
batch_t),
intent(inout) :: psib
942 real(real64),
intent(in) :: deltat
943 integer,
intent(in) :: k
947 complex(real64) :: deltat_
954 if (.not. hm%is_hermitian() .and. te%exp_method ==
exp_chebyshev)
then
955 write(
message(1),
'(a)')
'The Chebyshev expansion for the exponential will only converge if the imaginary'
956 write(
message(2),
'(a)')
'eigenvalues are small enough compared to the span of the real eigenvalues,'
957 write(
message(3),
'(a)')
'i.e., for ratios smaller than about 1e-3.'
958 write(
message(4),
'(a)')
'The Lanczos method ("TDExponentialMethod = lanczos") is guaranteed to'
959 write(
message(5),
'(a)')
'always converge in this case.'
963 if (
present(op))
then
969 deltat_ = cmplx(deltat,
m_zero, real64)
971 select case (te%exp_method)
978 else if (k == 2)
then
981 write(
message(1),
'(a)')
'Lanczos expansion not implemented for phi_k, k > 2'
988 else if (k == 2)
then
991 write(
message(1),
'(a)')
'Chebyshev expansion not implemented for phi_k, k > 2'
995 deallocate(chebyshev_function)
998 if (.not.
present(op))
then
999 safe_deallocate_p(op_)
1006 type(
namespace_t),
target,
intent(in) :: namespace
1007 class(
mesh_t),
target,
intent(in) :: mesh
1014 call this%init(namespace, mesh, hm)
1021 type(
namespace_t),
target,
intent(in) :: namespace
1022 class(
mesh_t),
target,
intent(in) :: mesh
1028 this%namespace => namespace
1036 class(
batch_t),
intent(inout) :: psib
1037 class(
batch_t),
intent(inout) :: hpsib
1041 call this%hm%zapply(this%namespace, this%mesh, psib, hpsib)
batchified version of the BLAS axpy routine:
batchified scale with optional conjugation:
scale a batch by a constant or vector
subroutine, public accel_finish()
This module implements batches of mesh functions.
This module implements common operations on batches of mesh functions.
This module contains interfaces for BLAS routines You should not use these routines directly....
subroutine, public exponential_copy(teo, tei)
subroutine, public exponential_apply_all(te, namespace, gr, hm, st, deltat, order)
Note that this routine not only computes the exponential, but also an extra term if there is a inhomo...
type(hamiltonian_operator_t) function, pointer hamiltonian_operator_constructor(namespace, mesh, hm)
subroutine exponential_cheby_batch(te, namespace, mesh, hm, psib, chebyshev_function, op)
Calculates the exponential of the Hamiltonian through an expansion in Chebyshev polynomials.
subroutine exponential_apply_phi_batch(te, namespace, mesh, hm, psib, deltat, k, op)
subroutine exponential_apply_batch(te, namespace, mesh, hm, psib, deltat, psib2, deltat2, imag_time, inh_psib, op)
This routine performs the operation:
subroutine hamiltonian_operator_init(this, namespace, mesh, hm)
subroutine, public exponential_lanczos_function_batch(te, namespace, mesh, hm, psib, deltat, fun, op)
Compute fun(H) psib, i.e. the application of a function of the Hamiltonian to a batch.
subroutine exponential_taylor_series_batch(te, namespace, mesh, hm, psib, deltat, op, psib2, deltat2, inh_psib, phik_shift)
subroutine, public exponential_init(te, namespace, full_batch)
integer, parameter, public exp_taylor
integer, parameter, public exp_chebyshev
subroutine exponential_apply_single(te, namespace, mesh, hm, zpsi, ist, ik, deltat, imag_time)
Wrapper to batchified routine for applying exponential to an array.
subroutine exponential_lanczos_batch(te, namespace, mesh, hm, psib, deltat, op, inh_psib)
subroutine hamiltonian_operator_apply(this, psib, hpsib)
real(real64), parameter, public m_two
real(real64), parameter, public m_zero
complex(real64), parameter, public m_zi
real(real64), parameter, public m_epsilon
complex(real64), parameter, public m_z1
real(real64), parameter, public m_one
This module implements the underlying real-space grid.
This module defines an abstract class for Hamiltonians.
subroutine, public zhamiltonian_elec_apply_all(hm, namespace, gr, st, hst)
pure logical function, public hamiltonian_elec_inh_term(hm)
subroutine, public zlalg_matrix_function(n, factor, a, fun_a, fun, hermitian, tridiagonal)
This routine calculates a function of a matrix by using an eigenvalue decomposition.
This module is intended to contain "only mathematical" functions and procedures.
complex(real64) pure function, public phi2(z)
Compute phi2(z) = (phi1(z)-1)/z = (exp(z) - z - 1)/z^2.
complex(real64) pure function, public exponential(z)
Wrapper for exponential.
complex(real64) pure function, public phi1(z)
Compute phi1(z) = (exp(z)-1)/z.
This module defines functions over batches of mesh functions.
subroutine, public mesh_batch_nrm2(mesh, aa, nrm2, reduce)
Calculate the norms (norm2, not the square!) of a batch of mesh functions.
subroutine, public zmesh_batch_orthogonalization(mesh, nst, psib, phib, normalize, overlap, norm, gs_scheme, full_batch)
Orthonormalizes states of phib to the orbitals of nst batches of psi.
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
subroutine, public messages_warning(no_lines, all_nodes, namespace)
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
subroutine, public messages_input_error(namespace, var, details, row, column)
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
logical function, public parse_is_defined(namespace, name)
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
subroutine, public states_elec_end(st)
finalize the states_elec_t object
subroutine, public states_elec_copy(stout, stin, exclude_wfns, exclude_eigenval, special)
make a (selective) copy of a states_elec_t object
type(type_t), parameter, public type_cmplx
Class defining batches of mesh functions.
Description of the grid, containing information on derivatives, stencil, and symmetries.
The abstract Hamiltonian class defines a skeleton for specific implementations.
Describes mesh distribution to nodes.
The states_elec_t class contains all electronic wave functions.
batches of electronic states