Octopus
exponential.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
2!! Copyright (C) 2019 M. Oliveira
3!!
4!! This program is free software; you can redistribute it and/or modify
5!! it under the terms of the GNU General Public License as published by
6!! the Free Software Foundation; either version 2, or (at your option)
7!! any later version.
8!!
9!! This program is distributed in the hope that it will be useful,
10!! but WITHOUT ANY WARRANTY; without even the implied warranty of
11!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12!! GNU General Public License for more details.
13!!
14!! You should have received a copy of the GNU General Public License
15!! along with this program; if not, write to the Free Software
16!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17!! 02110-1301, USA.
18!!
19
20#include "global.h"
21
23 use accel_oct_m
24 use batch_oct_m
26 use blas_oct_m
28 use debug_oct_m
29 use global_oct_m
30 use grid_oct_m
34 use, intrinsic :: iso_fortran_env
38 use math_oct_m
39 use mesh_oct_m
44 use parser_oct_m
48 use types_oct_m
50 use xc_oct_m
51
52 implicit none
53
54 private
55 public :: &
61 operator_t, &
63
64 integer, public, parameter :: &
65 EXP_LANCZOS = 2, &
66 exp_taylor = 3, &
68
69 type exponential_t
70 private
71 integer, public :: exp_method
72 real(real64) :: lanczos_tol
73 real(real64) :: chebyshev_tol
74 integer, public :: exp_order
75 integer :: arnoldi_gs
76 logical, public :: full_batch = .false.
77 contains
78 procedure :: apply_batch => exponential_apply_batch
79 procedure :: apply_single => exponential_apply_single
80 procedure :: apply_phi_batch => exponential_apply_phi_batch
81 end type exponential_t
82
83
84 type, abstract :: operator_t
85 type(namespace_t), pointer :: namespace
86 class(mesh_t), pointer :: mesh
87 contains
88 procedure(operator_apply), deferred :: apply
89 end type operator_t
90
91 abstract interface
92 subroutine operator_apply(this, psib, hpsib)
93 import operator_t
94 import batch_t
95 class(operator_t), intent(in) :: this
96 class(batch_t), intent(inout) :: psib
97 class(batch_t), intent(inout) :: hpsib
98 end subroutine operator_apply
99 end interface
100
101
102 type, extends(operator_t) :: hamiltonian_operator_t
103 class(hamiltonian_abst_t), pointer :: hm
104 contains
105 procedure :: apply => hamiltonian_operator_apply
106 procedure :: init => hamiltonian_operator_init
108
109 interface hamiltonian_operator_t
110 procedure hamiltonian_operator_constructor
111 end interface hamiltonian_operator_t
112
113contains
114
115 ! ---------------------------------------------------------
116 subroutine exponential_init(te, namespace, full_batch)
117 type(exponential_t), intent(out) :: te
118 type(namespace_t), intent(in) :: namespace
119 logical, optional, intent(in) :: full_batch
120
121 push_sub(exponential_init)
122
123 !%Variable TDExponentialMethod
124 !%Type integer
125 !%Default taylor
126 !%Section Time-Dependent::Propagation
127 !%Description
128 !% Method used to numerically calculate the exponential of the Hamiltonian,
129 !% a core part of the full algorithm used to approximate the evolution
130 !% operator, specified through the variable <tt>TDPropagator</tt>.
131 !% In the case of using the Magnus method, described below, the action of the exponential
132 !% of the Magnus operator is also calculated through the algorithm specified
133 !% by this variable.
134 !%Option lanczos 2
135 !% Allows for larger time-steps.
136 !% However, the larger the time-step, the longer the computational time per time-step.
137 !% In certain cases, if the time-step is too large, the code will emit a warning
138 !% whenever it considers that the evolution may not be properly proceeding --
139 !% the Lanczos process did not converge. The method consists in a Krylov
140 !% subspace approximation of the action of the exponential
141 !% (see M. Hochbruck and C. Lubich, <i>SIAM J. Numer. Anal.</i> <b>34</b>, 1911 (1997) for details).
142 !% The performance of the method is controlled by the tolerance (controlled by <tt>TDLanczosTol</tt>).
143 !% The smaller the tolerance, the more precisely the exponential
144 !% is calculated, but also the larger the dimension of the Arnoldi
145 !% subspace. If the maximum dimension (currently 200) is not enough to meet the criterion,
146 !% the above-mentioned warning is emitted.
147 !% Be aware that the larger the required dimension of the Krylov subspace, the larger
148 !% the memory required for this method. So if you run out of memory, try to reduce
149 !% the time step.
150 !%Option taylor 3
151 !% This method amounts to a straightforward application of the definition of
152 !% the exponential of an operator, in terms of its Taylor expansion.
153 !%
154 !% <math>\exp_{\rm STD} (-i\delta t H) = \sum_{i=0}^{k} {(-i\delta t)^i\over{i!}} H^i.</math>
155 !%
156 !% The order <i>k</i> is determined by variable <tt>TDExpOrder</tt>.
157 !% Some numerical considerations from <a href=http://www.phys.washington.edu/~bertsch/num3.ps>
158 !% Jeff Giansiracusa and George F. Bertsch</a>
159 !% suggest the 4th order as especially suitable and stable.
160 !%Option chebyshev 4
161 !% In principle, the Chebyshev expansion
162 !% of the exponential represents it more accurately than the canonical or standard expansion.
163 !% <tt>TDChebyshevTol</tt> determines the tolerance to which the expansion is computed.
164 !%
165 !% There exists a closed analytic form for the coefficients of the exponential in terms
166 !% of Chebyshev polynomials:
167 !%
168 !% <math>\exp_{\rm CHEB} \left( -i\delta t H \right) = \sum_{k=0}^{\infty} (2-\delta_{k0})(-i)^{k}J_k(\delta t) T_k(H),</math>
169 !%
170 !% where <math>J_k</math> are the Bessel functions of the first kind, and H has to be previously
171 !% scaled to <math>[-1,1]</math>.
172 !% See H. Tal-Ezer and R. Kosloff, <i>J. Chem. Phys.</i> <b>81</b>,
173 !% 3967 (1984); R. Kosloff, <i>Annu. Rev. Phys. Chem.</i> <b>45</b>, 145 (1994);
174 !% C. W. Clenshaw, <i>MTAC</i> <b>9</b>, 118 (1955).
175 !%End
176 call parse_variable(namespace, 'TDExponentialMethod', exp_taylor, te%exp_method)
177
178 select case (te%exp_method)
181 !%Variable TDChebyshevTol
182 !%Type float
183 !%Default 1e-10
184 !%Section Time-Dependent::Propagation
185 !%Description
186 !% An internal tolerance variable for the Chebyshev method. The smaller, the more
187 !% precisely the exponential is calculated and the more iterations are needed, i.e.,
188 !% it becomes more expensive. The expansion is terminated once the error estimate
189 !% is below this tolerance.
190 !%End
191 call parse_variable(namespace, 'TDChebyshevTol', 1e-10_real64, te%chebyshev_tol)
192 if (te%chebyshev_tol <= m_zero) call messages_input_error(namespace, 'TDChebyshevTol')
193 case (exp_lanczos)
194 !%Variable TDLanczosTol
195 !%Type float
196 !%Default 1e-6
197 !%Section Time-Dependent::Propagation
198 !%Description
199 !% An internal tolerance variable for the Lanczos method. The smaller, the more
200 !% precisely the exponential is calculated, and also the bigger the dimension
201 !% of the Krylov subspace needed to perform the algorithm. One should carefully
202 !% make sure that this value is not too big, or else the evolution will be
203 !% wrong.
204 !%End
205 call parse_variable(namespace, 'TDLanczosTol', 1e-6_real64, te%lanczos_tol)
206 if (te%lanczos_tol <= m_zero) call messages_input_error(namespace, 'TDLanczosTol')
207
208 case default
209 call messages_input_error(namespace, 'TDExponentialMethod')
210 end select
211 call messages_print_var_option('TDExponentialMethod', te%exp_method, namespace=namespace)
212
213 if (te%exp_method == exp_taylor) then
214 !%Variable TDExpOrder
215 !%Type integer
216 !%Default 4
217 !%Section Time-Dependent::Propagation
218 !%Description
219 !% For <tt>TDExponentialMethod</tt> = <tt>taylor</tt>,
220 !% the order to which the exponential is expanded.
221 !%End
222 call parse_variable(namespace, 'TDExpOrder', default__tdexporder, te%exp_order)
223 if (te%exp_order < 2) call messages_input_error(namespace, 'TDExpOrder')
224 else
225 if (parse_is_defined(namespace, 'TDExpOrder')) then
226 message(1) = "TDExpOrder is only relevant for TDExponentialMethod = taylor"
227 call messages_fatal(1, namespace=namespace)
228 end if
229 end if
230
231 te%arnoldi_gs = option__arnoldiorthogonalization__cgs
232 if (te%exp_method == exp_lanczos) then
233 !%Variable ArnoldiOrthogonalization
234 !%Type integer
235 !%Section Time-Dependent::Propagation
236 !%Description
237 !% The orthogonalization method used for the Arnoldi procedure.
238 !% Only for TDExponentialMethod = lanczos.
239 !%Option cgs 3
240 !% Classical Gram-Schmidt (CGS) orthogonalization.
241 !% The algorithm is defined in Giraud et al., Computers and Mathematics with Applications 50, 1069 (2005).
242 !%Option drcgs 5
243 !% Classical Gram-Schmidt orthogonalization with double-step reorthogonalization.
244 !% The algorithm is taken from Giraud et al., Computers and Mathematics with Applications 50, 1069 (2005).
245 !% According to this reference, this is much more precise than CGS or MGS algorithms.
246 !%End
247 call parse_variable(namespace, 'ArnoldiOrthogonalization', option__arnoldiorthogonalization__cgs, &
248 te%arnoldi_gs)
249 end if
250
251 ! do lanczos expansion for full batch?
252 te%full_batch = optional_default(full_batch, te%full_batch)
253
254 pop_sub(exponential_init)
255 end subroutine exponential_init
256
257 ! ---------------------------------------------------------
258 subroutine exponential_copy(teo, tei)
259 type(exponential_t), intent(inout) :: teo
260 type(exponential_t), intent(in) :: tei
261
262 push_sub(exponential_copy)
263
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
268
269 pop_sub(exponential_copy)
270 end subroutine exponential_copy
271
272 ! ---------------------------------------------------------
274 subroutine exponential_apply_single(te, namespace, mesh, hm, zpsi, ist, ik, deltat, imag_time)
275 class(exponential_t), intent(inout) :: te
276 type(namespace_t), intent(in) :: namespace
277 class(mesh_t), intent(in) :: mesh
278 type(hamiltonian_elec_t), intent(inout) :: hm
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
284
285 type(wfs_elec_t) :: psib, inh_psib
286 complex(real64), allocatable :: zpsi_inh(:, :)
287
289
290 !We apply the phase only to np points, and the phase for the np+1 to np_part points
291 !will be treated as a phase correction in the Hamiltonian
292 if (hm%phase%is_allocated()) then
293 call hm%phase%apply_to_single(zpsi, mesh%np, hm%d%dim, ik, .false.)
294 end if
295
296 call wfs_elec_init(psib, hm%d%dim, ist, ist, zpsi, ik)
297
298 if (hamiltonian_elec_inh_term(hm)) then
299 safe_allocate(zpsi_inh(1:mesh%np_part, 1:hm%d%dim))
300 call states_elec_get_state(hm%inh_st, mesh, ist, ik, zpsi_inh(:, :))
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)
304 call inh_psib%end()
305 safe_deallocate_a(zpsi_inh)
306 else
307 call te%apply_batch(namespace, mesh, hm, psib, deltat, &
308 imag_time=imag_time)
309 end if
310
311 call psib%end()
312
313 if (hm%phase%is_allocated()) then
314 call hm%phase%apply_to_single(zpsi, mesh%np, hm%d%dim, ik, .true.)
315 end if
316
318 end subroutine exponential_apply_single
319
320 ! ---------------------------------------------------------
337 ! ---------------------------------------------------------
338 subroutine exponential_apply_batch(te, namespace, mesh, hm, psib, deltat, psib2, deltat2, imag_time, inh_psib, op)
339 class(exponential_t), intent(inout) :: te
340 type(namespace_t), intent(in) :: namespace
341 class(mesh_t), intent(in) :: mesh
342 class(hamiltonian_abst_t), intent(inout) :: hm
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
350
351 complex(real64) :: deltat_, deltat2_
352 class(chebyshev_function_t), pointer :: chebyshev_function, chebyshev_function_dt2
353 logical :: imag_time_
354 class(operator_t), pointer :: op_
355
357 call profiling_in("EXPONENTIAL_BATCH")
358
359 assert(psib%type() == type_cmplx)
360
361 assert(present(psib2) .eqv. present(deltat2))
362 if (present(inh_psib)) then
363 assert(inh_psib%nst == psib%nst)
364 end if
365
366 if (present(op)) then
367 op_ => op
368 else
369 op_ => hamiltonian_operator_t(namespace, mesh, hm)
370 end if
371
372 deltat2_ = cmplx(optional_default(deltat2, m_zero), m_zero, real64)
373
374 imag_time_ = optional_default(imag_time, .false.)
375 if (imag_time_) then
376 deltat_ = -m_zi*deltat
377 if (present(deltat2)) deltat2_ = m_zi*deltat2
378 else
379 deltat_ = cmplx(deltat, m_zero, real64)
380 if (present(deltat2)) deltat2_ = cmplx(deltat2, m_zero, real64)
381 end if
382
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.'
387 call messages_fatal(3, namespace=namespace)
388 end if
389
390 select case (te%exp_method)
391 case (exp_taylor)
392 ! Note that delttat2_ is only initialized if deltat2 is present.
393 if (present(deltat2)) then
394 call exponential_taylor_series_batch(te, namespace, mesh, hm, psib, deltat_, op_, &
395 psib2, deltat2_)
396 else
397 call exponential_taylor_series_batch(te, namespace, mesh, hm, psib, deltat_, op_)
398 end if
399 if (present(inh_psib)) then
400 if (present(deltat2)) then
401 call exponential_taylor_series_batch(te, namespace, mesh, hm, psib, deltat_, op_, &
402 psib2, deltat2_, inh_psib)
403 else
404 call exponential_taylor_series_batch(te, namespace, mesh, hm, psib, deltat_, op_, &
405 inh_psib=inh_psib)
406 end if
407 end if
408
409 case (exp_lanczos)
410 if (present(psib2)) then
411 ! psib2 holds a copy of the starting vector; the Krylov basis is built once (driven by
412 ! psib) and both exp(-i*deltat*H) and exp(-i*deltat2*H) are reconstructed from it.
413 call psib%copy_data_to(mesh%np, psib2)
414 call exponential_lanczos_batch(te, namespace, mesh, hm, psib, deltat_, op_, &
415 psib2=psib2, deltat2=deltat2_)
416 if (present(inh_psib)) then
417 call exponential_lanczos_batch(te, namespace, mesh, hm, psib, deltat_, op_, inh_psib, &
418 psib2=psib2, deltat2=deltat2_)
419 end if
420 else
421 call exponential_lanczos_batch(te, namespace, mesh, hm, psib, deltat_, op_)
422 if (present(inh_psib)) then
423 call exponential_lanczos_batch(te, namespace, mesh, hm, psib, deltat_, op_, inh_psib)
424 end if
425 end if
426
427 case (exp_chebyshev)
428 if (present(inh_psib)) then
429 write(message(1), '(a)') 'Chebyshev exponential ("TDExponentialMethod = chebyshev")'
430 write(message(2), '(a)') 'with inhomogeneous term is not implemented'
431 call messages_fatal(2, namespace=namespace)
432 end if
433 ! initialize classes for computing coefficients
434 if (imag_time_) then
435 chebyshev_function => chebyshev_exp_imagtime_t(hm%spectral_half_span, hm%spectral_middle_point, deltat)
436 if (present(psib2)) then
437 chebyshev_function_dt2 => chebyshev_exp_imagtime_t(hm%spectral_half_span, hm%spectral_middle_point, deltat2)
438 end if
439 else
440 chebyshev_function => chebyshev_exp_t(hm%spectral_half_span, hm%spectral_middle_point, deltat)
441 if (present(psib2)) then
442 chebyshev_function_dt2 => chebyshev_exp_t(hm%spectral_half_span, hm%spectral_middle_point, deltat2)
443 end if
444 end if
445 if (present(psib2)) call psib%copy_data_to(mesh%np, psib2)
446 call exponential_cheby_batch(te, namespace, mesh, hm, psib, chebyshev_function, op_)
447 deallocate(chebyshev_function)
448 if (present(psib2)) then
449 call exponential_cheby_batch(te, namespace, mesh, hm, psib2, chebyshev_function_dt2, op_)
450 deallocate(chebyshev_function_dt2)
451 end if
452
453 end select
454
455 if (.not.present(op)) then
456 safe_deallocate_p(op_)
457 end if
458
459 call profiling_out("EXPONENTIAL_BATCH")
461 end subroutine exponential_apply_batch
462
463 ! ---------------------------------------------------------
464 subroutine exponential_taylor_series_batch(te, namespace, mesh, hm, psib, deltat, op, psib2, deltat2, inh_psib, phik_shift)
465 type(exponential_t), intent(inout) :: te
466 type(namespace_t), intent(in) :: namespace
467 class(mesh_t), intent(in) :: mesh
468 class(hamiltonian_abst_t), intent(inout) :: hm
469 class(batch_t), intent(inout) :: psib
470 complex(real64), intent(in) :: deltat
471 class(operator_t), intent(in) :: op
472 class(batch_t), optional, intent(inout) :: psib2
473 complex(real64), optional, intent(in) :: deltat2
474 class(batch_t), optional, intent(inout) :: inh_psib
475 integer, optional, intent(in) :: phik_shift
476
477 complex(real64) :: zfact, zfact2
478 integer :: iter, denom, phik_shift_
479 logical :: zfact_is_real
480 class(batch_t), allocatable :: psi1b, hpsi1b
481
483 call profiling_in("EXP_TAYLOR_BATCH")
484
485 call psib%clone_to(psi1b)
486 call psib%clone_to(hpsi1b)
487
488 zfact = m_z1
489 zfact2 = m_z1
490 zfact_is_real = abs(deltat-real(deltat, real64)) < m_epsilon
491
492 if (present(psib2)) call psib%copy_data_to(mesh%np, psib2)
493
494 if (present(inh_psib)) then
495 zfact = zfact*deltat
496 call batch_axpy(mesh%np, real(zfact, real64), inh_psib, psib)
497
498 if (present(psib2)) then
499 zfact2 = zfact2*deltat2
500 call batch_axpy(mesh%np, real(zfact2, real64), inh_psib, psib2)
501 end if
502 end if
503
504 ! shift the denominator by this shift for the phi_k functions
505 phik_shift_ = optional_default(phik_shift, 0)
506
507 do iter = 1, te%exp_order
508 denom = iter+phik_shift_
509 if (present(inh_psib)) denom = denom + 1
510 zfact = zfact*(-m_zi*deltat)/denom
511 if (present(deltat2)) zfact2 = zfact2*(-m_zi*deltat2)/denom
512 zfact_is_real = .not. zfact_is_real
513 ! FIXME: need a test here for runaway exponential, e.g. for too large dt.
514 ! in runaway case the problem is really hard to trace back: the positions
515 ! go haywire on the first step of dynamics (often NaN) and with debugging options
516 ! the code stops in ZAXPY below without saying why.
517
518 if (iter /= 1) then
519 call op%apply(psi1b, hpsi1b)
520 else
521 if (present(inh_psib)) then
522 call op%apply(inh_psib, hpsi1b)
523 else
524 call op%apply(psib, hpsi1b)
525 end if
526 end if
527
528 if (zfact_is_real) then
529 call batch_axpy(mesh%np, real(zfact, real64), hpsi1b, psib)
530 if (present(psib2)) call batch_axpy(mesh%np, real(zfact2, real64), hpsi1b, psib2)
531 else
532 call batch_axpy(mesh%np, zfact, hpsi1b, psib)
533 if (present(psib2)) call batch_axpy(mesh%np, zfact2, hpsi1b, psib2)
534 end if
535
536 if (iter /= te%exp_order) call hpsi1b%copy_data_to(mesh%np, psi1b)
537
538 end do
539
540 call psi1b%end()
541 call hpsi1b%end()
542 safe_deallocate_a(psi1b)
543 safe_deallocate_a(hpsi1b)
544
545 call profiling_out("EXP_TAYLOR_BATCH")
548
552 subroutine exponential_lanczos_batch(te, namespace, mesh, hm, psib, deltat, op, inh_psib, psib2, deltat2)
553 type(exponential_t), intent(inout) :: te
554 type(namespace_t), intent(in) :: namespace
555 class(mesh_t), intent(in) :: mesh
556 class(hamiltonian_abst_t), intent(inout) :: hm
557 class(batch_t), intent(inout) :: psib
558 complex(real64), intent(in) :: deltat
559 class(operator_t), intent(in) :: op
560 class(batch_t), optional, intent(in) :: inh_psib
561 class(batch_t), optional, intent(inout) :: psib2
562 complex(real64), optional, intent(in) :: deltat2
563
564 class(batch_t), allocatable :: tmpb, tmpb2
565
567
568 assert(present(psib2) .eqv. present(deltat2))
569
570 if (present(inh_psib)) then
571 call inh_psib%clone_to(tmpb, copy_data=.true.)
572 if (present(psib2)) then
573 ! psib = psib + deltat * phi1(-i*deltat *H) inh_psib
574 ! psib2 = psib2 + deltat2 * phi1(-i*deltat2*H) inh_psib (shared Krylov basis)
575 call inh_psib%clone_to(tmpb2, copy_data=.true.)
576 call exponential_lanczos_function_batch(te, namespace, mesh, hm, tmpb, deltat, phi1, op, &
577 psib2=tmpb2, deltat2=deltat2)
578 call batch_axpy(mesh%np, real(deltat, real64), tmpb, psib)
579 call batch_axpy(mesh%np, real(deltat2, real64), tmpb2, psib2)
580 call tmpb2%end()
581 safe_deallocate_a(tmpb2)
582 else
583 ! psib = psib + deltat * phi1(-i*deltat*H) inh_psib
584 call exponential_lanczos_function_batch(te, namespace, mesh, hm, tmpb, deltat, phi1, op)
585 call batch_axpy(mesh%np, real(deltat, real64), tmpb, psib)
586 end if
587 call tmpb%end()
588 safe_deallocate_a(tmpb)
589 else
590 if (present(psib2)) then
591 call exponential_lanczos_function_batch(te, namespace, mesh, hm, psib, deltat, exponential, op, &
592 psib2=psib2, deltat2=deltat2)
593 else
594 call exponential_lanczos_function_batch(te, namespace, mesh, hm, psib, deltat, exponential, op)
595 end if
596 end if
597
599 end subroutine exponential_lanczos_batch
600
601 ! ---------------------------------------------------------
615 subroutine exponential_lanczos_function_batch(te, namespace, mesh, hm, psib, deltat, fun, op, psib2, deltat2)
616 type(exponential_t), intent(inout) :: te
617 type(namespace_t), intent(in) :: namespace
618 class(mesh_t), intent(in) :: mesh
619 class(hamiltonian_abst_t), intent(inout) :: hm
620 class(batch_t), intent(inout) :: psib
621 complex(real64), intent(in) :: deltat
622 interface
623 complex(real64) function fun(z)
624 import real64
625 complex(real64), intent(in) :: z
626 end
627 end interface
628 class(operator_t), intent(in) :: op
629 class(batch_t), optional, intent(inout) :: psib2
630 complex(real64), optional, intent(in) :: deltat2
631
632 integer :: iter, l, ii, ist, max_initialized
633 complex(real64), allocatable :: hamilt(:,:,:), expo(:,:,:), expo2(:,:,:)
634 complex(real64), allocatable :: hamilt_tmp(:,:,:)
635 real(real64), allocatable :: beta(:), res(:), res2(:), norm(:)
636 integer, parameter :: max_order = 200
638 integer, parameter :: order_initial = 16
639 integer :: order_alloc
640 type(batch_p_t), allocatable :: vb(:) ! Krylov subspace vectors
641 logical :: have_dt2, converged, breakdown
642
644 call profiling_in("EXP_LANCZOS_FUN_BATCH")
645
646 if (te%exp_method /= exp_lanczos) then
647 message(1) = "The exponential method needs to be set to Lanzcos (TDExponentialMethod=lanczos)."
648 call messages_fatal(1)
649 end if
650
651 ! Optionally, a second exponential fun(deltat2*H) psib is computed reusing the same
652 ! Krylov basis and projected matrix (they do not depend on deltat), and written to psib2.
653 ! psib2 must already hold a copy of the input psib on entry (used as the starting vector
654 ! for the reconstruction), which is what the caller provides.
655 have_dt2 = present(psib2)
656 assert(present(psib2) .eqv. present(deltat2))
657 if (have_dt2) then
658 assert(psib2%nst == psib%nst)
659 end if
660
661 safe_allocate(beta(1:psib%nst))
662 safe_allocate(res(1:psib%nst))
663 safe_allocate(norm(1:psib%nst))
664 ! the residual is only computed from iteration 4 on; the non-convergence
665 ! message below prints maxval(res), so it must be defined even if the loop
666 ! somehow ends earlier
667 res = m_huge
668 safe_allocate(vb(1:max_order))
669 call psib%clone_to(vb(1)%p)
670 max_initialized = 1
671
672 ! Initialise starting Lanczos vector, v_1, from input wave function
673 call psib%copy_data_to(mesh%np, vb(1)%p, async=.true.)
674
675 ! Normalise v_1
676 ! Note, this is not the Lanczos coefficient
677 call mesh_batch_nrm2(mesh, vb(1)%p, beta)
678 if (te%full_batch) beta = norm2(beta)
679
680 ! If we have a null vector, no need to compute the action of the exponential.
681 if (all(abs(beta) <= 1.0e-12_real64)) then
682 safe_deallocate_a(beta)
683 safe_deallocate_a(res)
684 safe_deallocate_a(norm)
685 call vb(1)%p%end()
686 safe_deallocate_a(vb)
687 call profiling_out("EXP_LANCZOS_FUN_BATCH")
689 return
690 end if
691
692 call batch_scal(mesh%np, m_one/beta, vb(1)%p, a_full = .false.)
693
694 order_alloc = order_initial
695 safe_allocate(hamilt(1:order_alloc+1, 1:order_alloc+1, 1:psib%nst))
696 safe_allocate( expo(1:order_alloc+1, 1:order_alloc+1, 1:psib%nst))
697 if (have_dt2) then
698 safe_allocate(expo2(1:order_alloc+1, 1:order_alloc+1, 1:psib%nst))
699 safe_allocate(res2(1:psib%nst))
700 res2 = m_huge
701 end if
702
703 ! Lanczos loop
704 do iter = 1, max_order-1
705 ! Grow the projected matrices if the subspace outgrows them
706 if (iter + 1 > order_alloc) then
707 safe_allocate(hamilt_tmp(1:2*order_alloc+1, 1:2*order_alloc+1, 1:psib%nst))
708 hamilt_tmp = m_z0
709 hamilt_tmp(1:order_alloc+1, 1:order_alloc+1, :) = hamilt(:, :, :)
710 safe_deallocate_a(hamilt)
711 call move_alloc(hamilt_tmp, hamilt)
712 ! expo and expo2 are written before they are read, so nothing to keep
713 order_alloc = min(2*order_alloc, max_order)
714 safe_deallocate_a(expo)
715 safe_allocate(expo(1:order_alloc+1, 1:order_alloc+1, 1:psib%nst))
716 if (have_dt2) then
717 safe_deallocate_a(expo2)
718 safe_allocate(expo2(1:order_alloc+1, 1:order_alloc+1, 1:psib%nst))
719 end if
720 end if
721
722 call psib%clone_to(vb(iter + 1)%p)
723 max_initialized = iter + 1
724
725 ! Apply the operator (default is Hamiltonian), w = H v_j
726 call op%apply(vb(iter)%p, vb(iter+1)%p)
727
728 ! We use either the Lanczos method (Hermitian case) or the Arnoldi method
729 if (hm%is_hermitian()) then
730 ! The Lanczos projection is tridiagonal: T(i,j) = 0 for i < j-1.
731 hamilt(1:max(iter-2, 1), iter, 1:psib%nst) = m_zero
732 if (iter > 1) then
733 ! T(j-1,j) = beta_j
734 hamilt(iter-1, iter, 1:psib%nst) = hamilt(iter, iter-1, 1:psib%nst)
735 ! w = H v_j - beta_j v_{j-1}
736 call batch_axpy(mesh%np, -hamilt(iter-1, iter, 1:psib%nst), vb(iter-1)%p, vb(iter+1)%p, a_full = .false.)
737 end if
738 ! Only the projection onto v_j remains for the call below.
739 l = iter
740 else
741 ! Arnoldi projects against every existing basis vector v_1,...,v_j
742 l = 1
743 if (iter > 2) then
744 ! The projected matrix is upper Hessenberg: H(j,1:j-2) = 0
745 hamilt(iter, 1:iter-2, 1:psib%nst) = m_zero
746 end if
747 end if
748
749 ! Orthogonalize against previous vectors, where vb(iter+1)%p defines w on entry
750 ! For Lanczos, this routine computes 3 things:
751 ! (overlap): alpha_j = <v_j, w> returned to hamilt(j, j, :)
752 ! (norm): beta_{j+1} = ||r_j|| returned to hamilt(j+1, j, :)
753 ! (residual): r_j = w - alpha_j v_j returned in vb(j+1)%p, not normalised
754 ! For Arnoldi, this routine computes 3 things:
755 ! (overlap): h_{1:j,j} = <v_{1:j}, w> returned to hamilt(1:j, j, :)
756 ! (norm): h_{j+1,j} = ||r_j|| returned to hamilt(j+1, j, :)
757 ! (residual): r_j = w - sum_{i=1}^j h_{i,j} v_i in vb(j+1)%p, not normalised
758 call zmesh_batch_orthogonalization(mesh, iter - l + 1, vb(l:iter), vb(iter+1)%p, &
759 normalize = .false., overlap = hamilt(l:iter, iter, 1:psib%nst), norm = hamilt(iter + 1, iter, 1:psib%nst), &
760 gs_scheme = te%arnoldi_gs, full_batch = te%full_batch)
761
762 ! We now estimate the error we made. This is given by the formula denoted
763 ! Er2 in Sec. 5.2.
764 breakdown = all(abs(hamilt(iter + 1, iter, :)) < 1.0e4_real64*m_epsilon) ! "Happy breakdown"
765
766 ! We now need to compute exp(Hm), where Hm is the projection of the linear transformation
767 ! of the Hamiltonian onto the Krylov subspace Km
768 ! See Eq. 4
769 !
770 ! Note that in the Hermitian case, we use the Lanczos algorithm that requires
771 ! only a tridiagonal matrix. Else we have an upper Hessenberg matrix.
772 !
773 ! Compute the exponential only if it is potentially used: for happy breakdown and
774 ! for convergence at iteration >= 4. This saves a lot of time especially for small
775 ! iteration counts.
776 if (iter > 3 .or. breakdown) then
777 do ii = 1, psib%nst
778 call zlalg_matrix_function(iter, -m_zi*deltat, hamilt(:,:,ii), expo(:,:,ii), fun, &
779 hm%is_hermitian(), tridiagonal=hm%is_hermitian())
780 res(ii) = abs(hamilt(iter + 1, iter, ii) * abs(expo(iter, 1, ii)))
781 if (have_dt2) then
782 ! Reuse the same projected matrix hamilt; only the small-matrix function differs.
783 call zlalg_matrix_function(iter, -m_zi*deltat2, hamilt(:,:,ii), expo2(:,:,ii), fun, &
784 hm%is_hermitian(), tridiagonal=hm%is_hermitian())
785 res2(ii) = abs(hamilt(iter + 1, iter, ii) * abs(expo2(iter, 1, ii)))
786 end if
787 end do !ii
788 end if
789
790 if (breakdown) exit
791
792 ! Compute 1/beta_{j+1}
793 ! We normalize only if the norm is non-zero
794 ! see http://www.netlib.org/utk/people/JackDongarra/etemplates/node216.html#alg:arn0
795 norm = m_one
796 do ist = 1, psib%nst
797 if (abs(hamilt(iter + 1, iter, ist)) >= 1.0e4_real64 * m_epsilon) then
798 norm(ist) = m_one / abs(hamilt(iter + 1, iter, ist))
799 end if
800 end do
801
802 ! v_{j+1} = r_j / beta_{j+1}
803 call batch_scal(mesh%np, norm, vb(iter+1)%p, a_full = .false.)
804
805 ! When a second exponential shares this basis, require both to be
806 ! converged.
807 converged = .false.
808 if (iter > 3) then
809 converged = all(res < te%lanczos_tol)
810 if (converged .and. have_dt2) converged = all(res2 < te%lanczos_tol)
811 end if
812 if (converged) exit
813
814 end do !iter
815
816 if (iter == max_order) then ! Here one should consider the possibility of the happy breakdown.
817 write(message(1),'(a,i5,a,es9.2)') 'Lanczos exponential expansion did not converge after ', iter, &
818 ' iterations. Residual: ', maxval(res)
819 call messages_warning(1, namespace=namespace)
820 else
821 write(message(1),'(a,i5)') 'Debug: Lanczos exponential iterations: ', iter
822 call messages_info(1, namespace=namespace, debug_only=.true.)
823 end if
824
825 ! See Eq. 4 for the expression here
826 ! zpsi = nrm * V * expo(1:iter, 1) = nrm * V * expo * V^(T) * zpsi
827 ! psib (and, on entry, psib2) still holds the original starting vector = beta * vb(1).
828 call batch_scal(mesh%np, expo(1,1,1:psib%nst), psib, a_full = .false.)
829 ! TODO: We should have a routine batch_gemv for improved performance (see #1070 on gitlab)
830 do ii = 2, iter
831 call batch_axpy(mesh%np, beta(1:psib%nst)*expo(ii,1,1:psib%nst), vb(ii)%p, psib, a_full = .false.)
832 end do
833
834 ! Reconstruct the second exponential from the same Krylov basis vb, using expo2 (deltat2).
835 if (have_dt2) then
836 call batch_scal(mesh%np, expo2(1,1,1:psib%nst), psib2, a_full = .false.)
837 do ii = 2, iter
838 call batch_axpy(mesh%np, beta(1:psib%nst)*expo2(ii,1,1:psib%nst), vb(ii)%p, psib2, a_full = .false.)
839 end do
840 end if
841
842 do ii = 1, max_initialized
843 call vb(ii)%p%end()
844 end do
845
846 safe_deallocate_a(vb)
847 safe_deallocate_a(hamilt)
848 safe_deallocate_a(hamilt_tmp)
849 safe_deallocate_a(expo)
850 safe_deallocate_a(expo2)
851 safe_deallocate_a(beta)
852 safe_deallocate_a(res)
853 safe_deallocate_a(res2)
854 safe_deallocate_a(norm)
855
856 call accel_finish()
857
858 call profiling_out("EXP_LANCZOS_FUN_BATCH")
859
862
863
864 ! ---------------------------------------------------------
876 subroutine exponential_cheby_batch(te, namespace, mesh, hm, psib, chebyshev_function, op)
877 type(exponential_t), intent(inout) :: te
878 type(namespace_t), intent(in) :: namespace
879 class(mesh_t), intent(in) :: mesh
880 class(hamiltonian_abst_t), intent(inout) :: hm
881 class(batch_t), intent(inout) :: psib
882 class(chebyshev_function_t), intent(in) :: chebyshev_function
883 class(operator_t), intent(in) :: op
884
885 integer :: j, order_needed
886 complex(real64) :: coefficient
887 complex(real64), allocatable :: coefficients(:)
888 real(real64) :: error
889 class(batch_t), allocatable, target :: psi0, psi1, psi2
890 class(batch_t), pointer :: psi_n, psi_n1, psi_n2
891 integer, parameter :: max_order = 200
892
894 call profiling_in("EXP_CHEBY_BATCH")
895
896 call psib%clone_to(psi0)
897 call psib%clone_to(psi1)
898 call psib%clone_to(psi2)
899 call psib%copy_data_to(mesh%np, psi0)
900
901 order_needed = max_order
902 do j = 1, max_order
903 error = chebyshev_function%get_error(j)
904 if (error > m_zero .and. error < te%chebyshev_tol) then
905 order_needed = j
906 exit
907 end if
908 end do
909
910 call chebyshev_function%get_coefficients(j, coefficients)
911
912 ! zero-order term
913 call batch_scal(mesh%np, coefficients(0), psib)
914 ! first-order term
915 ! shifted Hamiltonian
916 call op%apply(psi0, psi1)
917 call batch_axpy(mesh%np, -hm%spectral_middle_point, psi0, psi1)
918 call batch_scal(mesh%np, m_one/hm%spectral_half_span, psi1)
919 ! accumulate result
920 call batch_axpy(mesh%np, coefficients(1), psi1, psib)
921
922 ! use pointers to avoid copies
923 psi_n => psi2
924 psi_n1 => psi1
925 psi_n2 => psi0
926
927 do j = 2, order_needed
928 ! compute shifted Hamiltonian and Chebyshev recurrence formula
929 call op%apply(psi_n1, psi_n)
930 call batch_axpy(mesh%np, -hm%spectral_middle_point, psi_n1, psi_n)
931 call batch_xpay(mesh%np, psi_n2, -m_two/hm%spectral_half_span, psi_n)
932 call batch_scal(mesh%np, -m_one, psi_n)
933
934 ! accumulate result
935 call batch_axpy(mesh%np, coefficients(j), psi_n, psib)
936
937 ! shift pointers for the three-term recurrence, this avoids copies
938 if (mod(j, 3) == 2) then
939 psi_n => psi0
940 psi_n1 => psi2
941 psi_n2 => psi1
942 else if (mod(j, 3) == 1) then
943 psi_n => psi2
944 psi_n1 => psi1
945 psi_n2 => psi0
946 else
947 psi_n => psi1
948 psi_n1 => psi0
949 psi_n2 => psi2
950 end if
951 end do
952
953 if (order_needed == max_order) then
954 write(message(1),'(a,i5,a,es9.2)') 'Chebyshev exponential expansion did not converge after ', j, &
955 ' iterations. Coefficient: ', coefficient
956 call messages_warning(1, namespace=namespace)
957 else
958 write(message(1),'(a,i5)') 'Debug: Chebyshev exponential iterations: ', j
959 call messages_info(1, namespace=namespace, debug_only=.true.)
960 end if
961
962 call psi0%end()
963 call psi1%end()
964 call psi2%end()
965 safe_deallocate_a(psi0)
966 safe_deallocate_a(psi1)
967 safe_deallocate_a(psi2)
968
969 safe_deallocate_a(coefficients)
970
971 call profiling_out("EXP_CHEBY_BATCH")
972
974 end subroutine exponential_cheby_batch
975
976 ! ---------------------------------------------------------
980 subroutine exponential_apply_all(te, namespace, gr, hm, st, deltat, order)
981 type(exponential_t), intent(inout) :: te
982 type(namespace_t), intent(in) :: namespace
983 type(grid_t), intent(inout) :: gr
984 type(hamiltonian_elec_t), intent(inout) :: hm
985 type(states_elec_t), intent(inout) :: st
986 real(real64), intent(in) :: deltat
987 integer, optional, intent(inout) :: order
988
989 integer :: ik, ib, i
990 real(real64) :: zfact
991
992 type(states_elec_t) :: st1, hst1
993
994 push_sub(exponential_apply_all)
995
996 assert(te%exp_method == exp_taylor)
997
998 call states_elec_copy(st1, st)
999 call states_elec_copy(hst1, st)
1000
1001 zfact = m_one
1002 do i = 1, te%exp_order
1003 zfact = zfact * deltat / i
1004
1005 if (i == 1) then
1006 call zhamiltonian_elec_apply_all(hm, namespace, gr, st, hst1)
1007 else
1008 call zhamiltonian_elec_apply_all(hm, namespace, gr, st1, hst1)
1009 end if
1010
1011 do ik = st%d%kpt%start, st%d%kpt%end
1012 do ib = st%group%block_start, st%group%block_end
1013 call batch_scal2v(gr%np, -m_zi, hst1%group%psib(ib, ik), st1%group%psib(ib, ik), conjugate_xx = .false.)
1014 call batch_axpy(gr%np, zfact, st1%group%psib(ib, ik), st%group%psib(ib, ik))
1015 end do
1016 end do
1017
1018 end do
1019 ! End of Taylor expansion loop.
1020
1021 call states_elec_end(st1)
1022 call states_elec_end(hst1)
1023
1024 ! We now add the inhomogeneous part, if present.
1025 if (hamiltonian_elec_inh_term(hm)) then
1026 !write(*, *) 'Now we apply the inhomogeneous term...'
1027
1028 call states_elec_copy(st1, hm%inh_st)
1029 call states_elec_copy(hst1, hm%inh_st)
1030
1031
1032 do ik = st%d%kpt%start, st%d%kpt%end
1033 do ib = st%group%block_start, st%group%block_end
1034 call batch_axpy(gr%np, deltat, st1%group%psib(ib, ik), st%group%psib(ib, ik))
1035 end do
1036 end do
1037
1038 zfact = m_one
1039 do i = 1, te%exp_order
1040 zfact = zfact * deltat / (i+1)
1041
1042 if (i == 1) then
1043 call zhamiltonian_elec_apply_all(hm, namespace, gr, hm%inh_st, hst1)
1044 else
1045 call zhamiltonian_elec_apply_all(hm, namespace, gr, st1, hst1)
1046 end if
1047
1048 do ik = st%d%kpt%start, st%d%kpt%end
1049 do ib = st%group%block_start, st%group%block_end
1050 call batch_scal2v(gr%np, -m_zi, hst1%group%psib(ib, ik), st1%group%psib(ib, ik), conjugate_xx = .false.)
1051 call batch_axpy(gr%np, deltat * zfact, st1%group%psib(ib, ik), st%group%psib(ib, ik))
1052 end do
1053 end do
1054
1055 end do
1056
1057 call states_elec_end(st1)
1058 call states_elec_end(hst1)
1059
1060 end if
1061
1062 if (present(order)) order = te%exp_order*st%nik*st%nst ! This should be the correct number
1063
1064 pop_sub(exponential_apply_all)
1065 end subroutine exponential_apply_all
1066
1067 subroutine exponential_apply_phi_batch(te, namespace, mesh, hm, psib, deltat, k, op)
1068 class(exponential_t), intent(inout) :: te
1069 type(namespace_t), intent(in) :: namespace
1070 class(mesh_t), intent(in) :: mesh
1071 class(hamiltonian_abst_t), intent(inout) :: hm
1072 class(batch_t), intent(inout) :: psib
1073 real(real64), intent(in) :: deltat
1074 integer, intent(in) :: k
1075 class(operator_t), target,optional, intent(in) :: op
1076
1077 class(chebyshev_function_t), pointer :: chebyshev_function
1078 complex(real64) :: deltat_
1079 class(operator_t), pointer :: op_
1080
1081 push_sub_with_profile(exponential_apply_phi_batch)
1082
1083 assert(psib%type() == type_cmplx)
1084
1085 if (.not. hm%is_hermitian() .and. te%exp_method == exp_chebyshev) then
1086 write(message(1), '(a)') 'The Chebyshev expansion for the exponential will only converge if the imaginary'
1087 write(message(2), '(a)') 'eigenvalues are small enough compared to the span of the real eigenvalues,'
1088 write(message(3), '(a)') 'i.e., for ratios smaller than about 1e-3.'
1089 write(message(4), '(a)') 'The Lanczos method ("TDExponentialMethod = lanczos") is guaranteed to'
1090 write(message(5), '(a)') 'always converge in this case.'
1091 call messages_warning(5, namespace=namespace)
1092 end if
1093
1094 if (present(op)) then
1095 op_ => op
1096 else
1097 op_ => hamiltonian_operator_t(namespace, mesh, hm)
1098 end if
1099
1100 deltat_ = cmplx(deltat, m_zero, real64)
1101
1102 select case (te%exp_method)
1103 case (exp_taylor)
1104 call exponential_taylor_series_batch(te, namespace, mesh, hm, psib, deltat_, op_, phik_shift=k)
1105
1106 case (exp_lanczos)
1107 if (k == 1) then
1108 call exponential_lanczos_function_batch(te, namespace, mesh, hm, psib, deltat_, phi1, op_)
1109 else if (k == 2) then
1110 call exponential_lanczos_function_batch(te, namespace, mesh, hm, psib, deltat_, phi2, op_)
1111 else
1112 write(message(1), '(a)') 'Lanczos expansion not implemented for phi_k, k > 2'
1113 call messages_fatal(1, namespace=namespace)
1114 end if
1115
1116 case (exp_chebyshev)
1117 if (k == 1) then
1118 chebyshev_function => chebyshev_numerical_t(hm%spectral_half_span, hm%spectral_middle_point, deltat, phi1)
1119 else if (k == 2) then
1120 chebyshev_function => chebyshev_numerical_t(hm%spectral_half_span, hm%spectral_middle_point, deltat, phi2)
1121 else
1122 write(message(1), '(a)') 'Chebyshev expansion not implemented for phi_k, k > 2'
1123 call messages_fatal(1, namespace=namespace)
1124 end if
1125 call exponential_cheby_batch(te, namespace, mesh, hm, psib, chebyshev_function, op_)
1126 deallocate(chebyshev_function)
1127 end select
1128
1129 if (.not.present(op)) then
1130 safe_deallocate_p(op_)
1131 end if
1132
1133 pop_sub_with_profile(exponential_apply_phi_batch)
1134 end subroutine exponential_apply_phi_batch
1135
1136 function hamiltonian_operator_constructor(namespace, mesh, hm) result(this)
1137 type(namespace_t), target, intent(in) :: namespace
1138 class(mesh_t), target, intent(in) :: mesh
1139 class(hamiltonian_abst_t), target, intent(in) :: hm
1140 type(hamiltonian_operator_t), pointer :: this
1141
1143
1144 allocate(this)
1145 call this%init(namespace, mesh, hm)
1146
1149
1150 subroutine hamiltonian_operator_init(this, namespace, mesh, hm)
1151 class(hamiltonian_operator_t), intent(inout) :: this
1152 type(namespace_t), target, intent(in) :: namespace
1153 class(mesh_t), target, intent(in) :: mesh
1154 class(hamiltonian_abst_t), target, intent(in) :: hm
1155
1157
1158 this%mesh => mesh
1159 this%namespace => namespace
1160 this%hm => hm
1161
1163 end subroutine hamiltonian_operator_init
1164
1165 subroutine hamiltonian_operator_apply(this, psib, hpsib)
1166 class(hamiltonian_operator_t), intent(in) :: this
1167 class(batch_t), intent(inout) :: psib
1168 class(batch_t), intent(inout) :: hpsib
1169
1171
1172 call this%hm%zapply(this%namespace, this%mesh, psib, hpsib)
1173
1175 end subroutine hamiltonian_operator_apply
1176
1177end module exponential_oct_m
1178
1179!! Local Variables:
1180!! mode: f90
1181!! coding: utf-8
1182!! End:
batchified version of the BLAS axpy routine:
Definition: batch_ops.F90:160
batchified scale with optional conjugation:
Definition: batch_ops.F90:184
scale a batch by a constant or vector
Definition: batch_ops.F90:170
batchified version of
Definition: batch_ops.F90:190
subroutine, public accel_finish()
Definition: accel.F90:1127
This module implements batches of mesh functions.
Definition: batch.F90:135
This module implements common operations on batches of mesh functions.
Definition: batch_ops.F90:118
This module contains interfaces for BLAS routines You should not use these routines directly....
Definition: blas.F90:120
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_lanczos_batch(te, namespace, mesh, hm, psib, deltat, op, inh_psib, psib2, deltat2)
Lanczos/Arnoldi procedure for the exponential of an operator.
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 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)
subroutine, public exponential_lanczos_function_batch(te, namespace, mesh, hm, psib, deltat, fun, op, psib2, deltat2)
Compute fun(H) psib, i.e. the application of a function of the Hamiltonian to a 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 hamiltonian_operator_apply(this, psib, hpsib)
real(real64), parameter, public m_two
Definition: global.F90:202
real(real64), parameter, public m_huge
Definition: global.F90:218
real(real64), parameter, public m_zero
Definition: global.F90:200
complex(real64), parameter, public m_z0
Definition: global.F90:210
complex(real64), parameter, public m_zi
Definition: global.F90:214
real(real64), parameter, public m_epsilon
Definition: global.F90:216
complex(real64), parameter, public m_z1
Definition: global.F90:211
real(real64), parameter, public m_one
Definition: global.F90:201
This module implements the underlying real-space grid.
Definition: grid.F90:119
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.
Definition: lalg_adv.F90:2115
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:117
complex(real64) pure function, public phi2(z)
Compute phi2(z) = (phi1(z)-1)/z = (exp(z) - z - 1)/z^2.
Definition: math.F90:930
complex(real64) pure function, public exponential(z)
Wrapper for exponential.
Definition: math.F90:899
complex(real64) pure function, public phi1(z)
Compute phi1(z) = (exp(z)-1)/z.
Definition: math.F90:911
This module defines functions over batches of mesh functions.
Definition: mesh_batch.F90:118
subroutine, public mesh_batch_nrm2(mesh, aa, nrm2, reduce)
Calculate the norms (norm2, not the square!) of a batch of mesh functions.
Definition: mesh_batch.F90:180
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.
Definition: mesh.F90:120
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:525
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:410
subroutine, public messages_input_error(namespace, var, details, row, column)
Definition: messages.F90:691
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:594
logical function, public parse_is_defined(namespace, name)
Definition: parser.F90:463
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
Definition: profiling.F90:631
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Definition: profiling.F90:554
subroutine, public states_elec_end(st)
finalize the states_elec_t object
subroutine, public states_elec_copy(stout, stin, exclude_wfns, exclude_eigenval, special, dest_type, copy_data)
make a (selective) copy of a states_elec_t object
type(type_t), parameter, public type_cmplx
Definition: types.F90:137
Definition: xc.F90:120
Class defining batches of mesh functions.
Definition: batch.F90:164
Description of the grid, containing information on derivatives, stencil, and symmetries.
Definition: grid.F90:171
The abstract Hamiltonian class defines a skeleton for specific implementations.
Describes mesh distribution to nodes.
Definition: mesh.F90:187
The states_elec_t class contains all electronic wave functions.
batches of electronic states
Definition: wfs_elec.F90:143
int true(void)