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)) <
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), inh_psib, psib)
493 if (
present(psib2))
then
494 zfact2 = zfact2*deltat2
495 call batch_axpy(mesh%np, real(zfact2), 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), hpsi1b, psib)
525 if (
present(psib2))
call batch_axpy(mesh%np, real(zfact2), 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)
586 class(
mesh_t),
intent(in) :: mesh
588 class(
batch_t),
intent(inout) :: psib
589 complex(real64),
intent(in) :: deltat
591 complex(real64) function fun(z)
593 complex(real64),
intent(in) :: z
598 integer :: iter, l, ii, ist, max_initialized
599 complex(real64),
allocatable :: hamilt(:,:,:), expo(:,:,:)
600 real(real64),
allocatable :: beta(:), res(:), norm(:)
601 integer,
parameter :: max_order = 200
607 if (te%exp_method /= exp_lanczos)
then
608 message(1) =
"The exponential method needs to be set to Lanzcos (TDExponentialMethod=lanczos)."
612 safe_allocate(beta(1:psib%nst))
613 safe_allocate(res(1:psib%nst))
614 safe_allocate(norm(1:psib%nst))
615 safe_allocate(vb(1:max_order))
616 call psib%clone_to(vb(1)%p)
619 call psib%copy_data_to(mesh%np, vb(1)%p, async=.
true.)
622 if (te%full_batch) beta = norm2(beta)
625 if (all(abs(beta) <= 1.0e-12_real64))
then
626 safe_deallocate_a(beta)
627 safe_deallocate_a(res)
628 safe_deallocate_a(norm)
630 safe_deallocate_a(vb)
638 safe_allocate(hamilt(1:max_order+1, 1:max_order+1, 1:psib%nst))
639 safe_allocate( expo(1:max_order+1, 1:max_order+1, 1:psib%nst))
642 do iter = 1, max_order-1
643 call psib%clone_to(vb(iter + 1)%p)
644 max_initialized = iter + 1
647 call op%apply(vb(iter)%p, vb(iter+1)%p)
650 if (hm%is_hermitian())
then
652 hamilt(1:max(l-1, 1), iter, 1:psib%nst) =
m_zero
656 hamilt(iter, 1:iter-2, 1:psib%nst) =
m_zero
662 normalize = .false., overlap = hamilt(l:iter, iter, 1:psib%nst), norm = hamilt(iter + 1, iter, 1:psib%nst), &
663 gs_scheme = te%arnoldi_gs, full_batch = te%full_batch)
673 hm%is_hermitian(), tridiagonal=hm%is_hermitian())
674 res(ii) = abs(hamilt(iter + 1, iter, ii) * abs(expo(iter, 1, ii)))
678 if (all(abs(hamilt(iter + 1, iter, :)) < 1.0e4_real64*
m_epsilon))
exit
683 if (abs(hamilt(iter + 1, iter, ist)) >= 1.0e4_real64 *
m_epsilon)
then
684 norm(ist) =
m_one / abs(hamilt(iter + 1, iter, ist))
688 call batch_scal(mesh%np, norm, vb(iter+1)%p, a_full = .false.)
690 if (iter > 3 .and. all(res < te%lanczos_tol))
exit
694 if (iter == max_order)
then
695 write(
message(1),
'(a,i5,a,es9.2)')
'Lanczos exponential expansion did not converge after ', iter, &
696 ' iterations. Residual: ', maxval(res)
699 write(
message(1),
'(a,i5)')
'Debug: Lanczos exponential iterations: ', iter
705 call batch_scal(mesh%np, expo(1,1,1:psib%nst), psib, a_full = .false.)
708 call batch_axpy(mesh%np, beta(1:psib%nst)*expo(ii,1,1:psib%nst), vb(ii)%p, psib, a_full = .false.)
713 do ii = 1, max_initialized
717 safe_deallocate_a(vb)
718 safe_deallocate_a(hamilt)
719 safe_deallocate_a(expo)
720 safe_deallocate_a(beta)
721 safe_deallocate_a(res)
722 safe_deallocate_a(norm)
747 class(
mesh_t),
intent(in) :: mesh
749 class(
batch_t),
intent(inout) :: psib
753 integer :: j, order_needed
754 complex(real64) :: coefficient
755 complex(real64),
allocatable :: coefficients(:)
756 real(real64) :: error
757 class(
batch_t),
allocatable,
target :: psi0, psi1, psi2
758 class(
batch_t),
pointer :: psi_n, psi_n1, psi_n2
759 integer,
parameter :: max_order = 200
764 call psib%clone_to(psi0)
765 call psib%clone_to(psi1)
766 call psib%clone_to(psi2)
767 call psib%copy_data_to(mesh%np, psi0)
769 order_needed = max_order
771 error = chebyshev_function%get_error(j)
772 if (error >
m_zero .and. error < te%chebyshev_tol)
then
778 call chebyshev_function%get_coefficients(j, coefficients)
781 call batch_scal(mesh%np, coefficients(0), psib)
784 call op%apply(psi0, psi1)
785 call batch_axpy(mesh%np, -hm%spectral_middle_point, psi0, psi1)
788 call batch_axpy(mesh%np, coefficients(1), psi1, psib)
795 do j = 2, order_needed
797 call op%apply(psi_n1, psi_n)
798 call batch_axpy(mesh%np, -hm%spectral_middle_point, psi_n1, psi_n)
803 call batch_axpy(mesh%np, coefficients(j), psi_n, psib)
806 if (mod(j, 3) == 2)
then
810 else if (mod(j, 3) == 1)
then
821 if (order_needed == max_order)
then
822 write(
message(1),
'(a,i5,a,es9.2)')
'Chebyshev exponential expansion did not converge after ', j, &
823 ' iterations. Coefficient: ', coefficient
826 write(
message(1),
'(a,i5)')
'Debug: Chebyshev exponential iterations: ', j
833 safe_deallocate_a(psi0)
834 safe_deallocate_a(psi1)
835 safe_deallocate_a(psi2)
837 safe_deallocate_a(coefficients)
851 type(
grid_t),
intent(inout) :: gr
854 real(real64),
intent(in) :: deltat
855 integer,
optional,
intent(inout) :: order
858 real(real64) :: zfact
870 do i = 1, te%exp_order
871 zfact = zfact * deltat / i
879 do ik = st%d%kpt%start, st%d%kpt%end
880 do ib = st%group%block_start, st%group%block_end
882 call batch_axpy(gr%np, -
m_zi, hst1%group%psib(ib, ik), st1%group%psib(ib, ik))
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
920 call batch_axpy(gr%np, -
m_zi, hst1%group%psib(ib, ik), st1%group%psib(ib, ik))
921 call batch_axpy(gr%np, deltat * zfact, st1%group%psib(ib, ik), st%group%psib(ib, ik))
932 if (
present(order)) order = te%exp_order*st%nik*st%nst
940 class(
mesh_t),
intent(in) :: mesh
942 class(
batch_t),
intent(inout) :: psib
943 real(real64),
intent(in) :: deltat
944 integer,
intent(in) :: k
945 class(
operator_t),
target,
optional,
intent(in) :: op
948 complex(real64) :: deltat_
955 if (.not. hm%is_hermitian() .and. te%exp_method ==
exp_chebyshev)
then
956 write(
message(1),
'(a)')
'The Chebyshev expansion for the exponential will only converge if the imaginary'
957 write(
message(2),
'(a)')
'eigenvalues are small enough compared to the span of the real eigenvalues,'
958 write(
message(3),
'(a)')
'i.e., for ratios smaller than about 1e-3.'
959 write(
message(4),
'(a)')
'The Lanczos method ("TDExponentialMethod = lanczos") is guaranteed to'
960 write(
message(5),
'(a)')
'always converge in this case.'
964 if (
present(op))
then
970 deltat_ = cmplx(deltat,
m_zero, real64)
972 select case (te%exp_method)
979 else if (k == 2)
then
982 write(
message(1),
'(a)')
'Lanczos expansion not implemented for phi_k, k > 2'
989 else if (k == 2)
then
992 write(
message(1),
'(a)')
'Chebyshev expansion not implemented for phi_k, k > 2'
996 deallocate(chebyshev_function)
999 if (.not.
present(op))
then
1000 safe_deallocate_p(op_)
1007 type(
namespace_t),
target,
intent(in) :: namespace
1008 class(
mesh_t),
target,
intent(in) :: mesh
1015 call this%init(namespace, mesh, hm)
1022 type(
namespace_t),
target,
intent(in) :: namespace
1023 class(
mesh_t),
target,
intent(in) :: mesh
1029 this%namespace => namespace
1037 class(
batch_t),
intent(inout) :: psib
1038 class(
batch_t),
intent(inout) :: hpsib
1042 call this%hm%zapply(this%namespace, this%mesh, psib, hpsib)
batchified version of the BLAS axpy routine:
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.
subroutine, public batch_set_zero(this, np, async)
fill all mesh functions of the batch with zero
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), 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