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 call psib%copy_data_to(mesh%np, vb(1)%p, async=.true.)
673 call mesh_batch_nrm2(mesh, vb(1)%p, beta)
674
675 if (te%full_batch) beta = norm2(beta)
676
677 ! If we have a null vector, no need to compute the action of the exponential.
678 if (all(abs(beta) <= 1.0e-12_real64)) then
679 safe_deallocate_a(beta)
680 safe_deallocate_a(res)
681 safe_deallocate_a(norm)
682 call vb(1)%p%end()
683 safe_deallocate_a(vb)
684 call profiling_out("EXP_LANCZOS_FUN_BATCH")
686 return
687 end if
688
689 call batch_scal(mesh%np, m_one/beta, vb(1)%p, a_full = .false.)
690
691 order_alloc = order_initial
692 safe_allocate(hamilt(1:order_alloc+1, 1:order_alloc+1, 1:psib%nst))
693 safe_allocate( expo(1:order_alloc+1, 1:order_alloc+1, 1:psib%nst))
694 if (have_dt2) then
695 safe_allocate(expo2(1:order_alloc+1, 1:order_alloc+1, 1:psib%nst))
696 safe_allocate(res2(1:psib%nst))
697 res2 = m_huge
698 end if
699
700 ! This is the Lanczos loop...
701 do iter = 1, max_order-1
702 ! Grow the projected matrices if the subspace outgrows them
703 if (iter + 1 > order_alloc) then
704 safe_allocate(hamilt_tmp(1:2*order_alloc+1, 1:2*order_alloc+1, 1:psib%nst))
705 hamilt_tmp = m_z0
706 hamilt_tmp(1:order_alloc+1, 1:order_alloc+1, :) = hamilt(:, :, :)
707 safe_deallocate_a(hamilt)
708 call move_alloc(hamilt_tmp, hamilt)
709 ! expo and expo2 are written before they are read, so nothing to keep
710 order_alloc = min(2*order_alloc, max_order)
711 safe_deallocate_a(expo)
712 safe_allocate(expo(1:order_alloc+1, 1:order_alloc+1, 1:psib%nst))
713 if (have_dt2) then
714 safe_deallocate_a(expo2)
715 safe_allocate(expo2(1:order_alloc+1, 1:order_alloc+1, 1:psib%nst))
716 end if
717 end if
718
719 call psib%clone_to(vb(iter + 1)%p)
720 max_initialized = iter + 1
721
722 ! to apply the operator (default is Hamiltonian)
723 call op%apply(vb(iter)%p, vb(iter+1)%p)
724
725 ! We use either the Lanczos method (Hermitian case) or the Arnoldi method
726 if (hm%is_hermitian()) then
727 l = max(1, iter - 1)
728 hamilt(1:max(l-1, 1), iter, 1:psib%nst) = m_zero
729 else
730 l = 1
731 if (iter > 2) then
732 hamilt(iter, 1:iter-2, 1:psib%nst) = m_zero
733 end if
734 end if
735
736 ! Orthogonalize against previous vectors
737 call zmesh_batch_orthogonalization(mesh, iter - l + 1, vb(l:iter), vb(iter+1)%p, &
738 normalize = .false., overlap = hamilt(l:iter, iter, 1:psib%nst), norm = hamilt(iter + 1, iter, 1:psib%nst), &
739 gs_scheme = te%arnoldi_gs, full_batch = te%full_batch)
740
741 ! We now estimate the error we made. This is given by the formula denoted
742 ! Er2 in Sec. 5.2.
743 breakdown = all(abs(hamilt(iter + 1, iter, :)) < 1.0e4_real64*m_epsilon) ! "Happy breakdown"
744
745 ! We now need to compute exp(Hm), where Hm is the projection of the linear transformation
746 ! of the Hamiltonian onto the Krylov subspace Km
747 ! See Eq. 4
748 !
749 ! Note that in the Hermitian case, we use the Lanczos algorithm that requires
750 ! only a tridiagonal matrix. Else we have an upper Hessenberg matrix.
751 !
752 ! Compute the exponential only if it is potentially used: for happy breakdown and
753 ! for convergence at iteration >= 4. This saves a lot of time especially for small
754 ! iteration counts.
755 if (iter > 3 .or. breakdown) then
756 do ii = 1, psib%nst
757 call zlalg_matrix_function(iter, -m_zi*deltat, hamilt(:,:,ii), expo(:,:,ii), fun, &
758 hm%is_hermitian(), tridiagonal=hm%is_hermitian())
759 res(ii) = abs(hamilt(iter + 1, iter, ii) * abs(expo(iter, 1, ii)))
760 if (have_dt2) then
761 ! Reuse the same projected matrix hamilt; only the small-matrix function differs.
762 call zlalg_matrix_function(iter, -m_zi*deltat2, hamilt(:,:,ii), expo2(:,:,ii), fun, &
763 hm%is_hermitian(), tridiagonal=hm%is_hermitian())
764 res2(ii) = abs(hamilt(iter + 1, iter, ii) * abs(expo2(iter, 1, ii)))
765 end if
766 end do !ii
767 end if
768
769 if (breakdown) exit
770 ! We normalize only if the norm is non-zero
771 ! see http://www.netlib.org/utk/people/JackDongarra/etemplates/node216.html#alg:arn0
772 norm = m_one
773 do ist = 1, psib%nst
774 if (abs(hamilt(iter + 1, iter, ist)) >= 1.0e4_real64 * m_epsilon) then
775 norm(ist) = m_one / abs(hamilt(iter + 1, iter, ist))
776 end if
777 end do
778
779 call batch_scal(mesh%np, norm, vb(iter+1)%p, a_full = .false.)
780
781 ! When a second exponential shares this basis, require both to be
782 ! converged.
783 converged = .false.
784 if (iter > 3) then
785 converged = all(res < te%lanczos_tol)
786 if (converged .and. have_dt2) converged = all(res2 < te%lanczos_tol)
787 end if
788 if (converged) exit
789
790 end do !iter
791
792 if (iter == max_order) then ! Here one should consider the possibility of the happy breakdown.
793 write(message(1),'(a,i5,a,es9.2)') 'Lanczos exponential expansion did not converge after ', iter, &
794 ' iterations. Residual: ', maxval(res)
795 call messages_warning(1, namespace=namespace)
796 else
797 write(message(1),'(a,i5)') 'Debug: Lanczos exponential iterations: ', iter
798 call messages_info(1, namespace=namespace, debug_only=.true.)
799 end if
800
801 ! See Eq. 4 for the expression here
802 ! zpsi = nrm * V * expo(1:iter, 1) = nrm * V * expo * V^(T) * zpsi
803 ! psib (and, on entry, psib2) still holds the original starting vector = beta * vb(1).
804 call batch_scal(mesh%np, expo(1,1,1:psib%nst), psib, a_full = .false.)
805 ! TODO: We should have a routine batch_gemv for improved performance (see #1070 on gitlab)
806 do ii = 2, iter
807 call batch_axpy(mesh%np, beta(1:psib%nst)*expo(ii,1,1:psib%nst), vb(ii)%p, psib, a_full = .false.)
808 end do
809
810 ! Reconstruct the second exponential from the same Krylov basis vb, using expo2 (deltat2).
811 if (have_dt2) then
812 call batch_scal(mesh%np, expo2(1,1,1:psib%nst), psib2, a_full = .false.)
813 do ii = 2, iter
814 call batch_axpy(mesh%np, beta(1:psib%nst)*expo2(ii,1,1:psib%nst), vb(ii)%p, psib2, a_full = .false.)
815 end do
816 end if
817
818 do ii = 1, max_initialized
819 call vb(ii)%p%end()
820 end do
821
822 safe_deallocate_a(vb)
823 safe_deallocate_a(hamilt)
824 safe_deallocate_a(hamilt_tmp)
825 safe_deallocate_a(expo)
826 safe_deallocate_a(expo2)
827 safe_deallocate_a(beta)
828 safe_deallocate_a(res)
829 safe_deallocate_a(res2)
830 safe_deallocate_a(norm)
831
832 call accel_finish()
833
834 call profiling_out("EXP_LANCZOS_FUN_BATCH")
835
838
839
840 ! ---------------------------------------------------------
852 subroutine exponential_cheby_batch(te, namespace, mesh, hm, psib, chebyshev_function, op)
853 type(exponential_t), intent(inout) :: te
854 type(namespace_t), intent(in) :: namespace
855 class(mesh_t), intent(in) :: mesh
856 class(hamiltonian_abst_t), intent(inout) :: hm
857 class(batch_t), intent(inout) :: psib
858 class(chebyshev_function_t), intent(in) :: chebyshev_function
859 class(operator_t), intent(in) :: op
860
861 integer :: j, order_needed
862 complex(real64) :: coefficient
863 complex(real64), allocatable :: coefficients(:)
864 real(real64) :: error
865 class(batch_t), allocatable, target :: psi0, psi1, psi2
866 class(batch_t), pointer :: psi_n, psi_n1, psi_n2
867 integer, parameter :: max_order = 200
868
870 call profiling_in("EXP_CHEBY_BATCH")
871
872 call psib%clone_to(psi0)
873 call psib%clone_to(psi1)
874 call psib%clone_to(psi2)
875 call psib%copy_data_to(mesh%np, psi0)
876
877 order_needed = max_order
878 do j = 1, max_order
879 error = chebyshev_function%get_error(j)
880 if (error > m_zero .and. error < te%chebyshev_tol) then
881 order_needed = j
882 exit
883 end if
884 end do
885
886 call chebyshev_function%get_coefficients(j, coefficients)
887
888 ! zero-order term
889 call batch_scal(mesh%np, coefficients(0), psib)
890 ! first-order term
891 ! shifted Hamiltonian
892 call op%apply(psi0, psi1)
893 call batch_axpy(mesh%np, -hm%spectral_middle_point, psi0, psi1)
894 call batch_scal(mesh%np, m_one/hm%spectral_half_span, psi1)
895 ! accumulate result
896 call batch_axpy(mesh%np, coefficients(1), psi1, psib)
897
898 ! use pointers to avoid copies
899 psi_n => psi2
900 psi_n1 => psi1
901 psi_n2 => psi0
902
903 do j = 2, order_needed
904 ! compute shifted Hamiltonian and Chebyshev recurrence formula
905 call op%apply(psi_n1, psi_n)
906 call batch_axpy(mesh%np, -hm%spectral_middle_point, psi_n1, psi_n)
907 call batch_xpay(mesh%np, psi_n2, -m_two/hm%spectral_half_span, psi_n)
908 call batch_scal(mesh%np, -m_one, psi_n)
909
910 ! accumulate result
911 call batch_axpy(mesh%np, coefficients(j), psi_n, psib)
912
913 ! shift pointers for the three-term recurrence, this avoids copies
914 if (mod(j, 3) == 2) then
915 psi_n => psi0
916 psi_n1 => psi2
917 psi_n2 => psi1
918 else if (mod(j, 3) == 1) then
919 psi_n => psi2
920 psi_n1 => psi1
921 psi_n2 => psi0
922 else
923 psi_n => psi1
924 psi_n1 => psi0
925 psi_n2 => psi2
926 end if
927 end do
928
929 if (order_needed == max_order) then
930 write(message(1),'(a,i5,a,es9.2)') 'Chebyshev exponential expansion did not converge after ', j, &
931 ' iterations. Coefficient: ', coefficient
932 call messages_warning(1, namespace=namespace)
933 else
934 write(message(1),'(a,i5)') 'Debug: Chebyshev exponential iterations: ', j
935 call messages_info(1, namespace=namespace, debug_only=.true.)
936 end if
937
938 call psi0%end()
939 call psi1%end()
940 call psi2%end()
941 safe_deallocate_a(psi0)
942 safe_deallocate_a(psi1)
943 safe_deallocate_a(psi2)
944
945 safe_deallocate_a(coefficients)
946
947 call profiling_out("EXP_CHEBY_BATCH")
948
950 end subroutine exponential_cheby_batch
951
952 ! ---------------------------------------------------------
956 subroutine exponential_apply_all(te, namespace, gr, hm, st, deltat, order)
957 type(exponential_t), intent(inout) :: te
958 type(namespace_t), intent(in) :: namespace
959 type(grid_t), intent(inout) :: gr
960 type(hamiltonian_elec_t), intent(inout) :: hm
961 type(states_elec_t), intent(inout) :: st
962 real(real64), intent(in) :: deltat
963 integer, optional, intent(inout) :: order
964
965 integer :: ik, ib, i
966 real(real64) :: zfact
967
968 type(states_elec_t) :: st1, hst1
969
970 push_sub(exponential_apply_all)
971
972 assert(te%exp_method == exp_taylor)
973
974 call states_elec_copy(st1, st)
975 call states_elec_copy(hst1, st)
976
977 zfact = m_one
978 do i = 1, te%exp_order
979 zfact = zfact * deltat / i
980
981 if (i == 1) then
982 call zhamiltonian_elec_apply_all(hm, namespace, gr, st, hst1)
983 else
984 call zhamiltonian_elec_apply_all(hm, namespace, gr, st1, hst1)
985 end if
986
987 do ik = st%d%kpt%start, st%d%kpt%end
988 do ib = st%group%block_start, st%group%block_end
989 call batch_scal2v(gr%np, -m_zi, hst1%group%psib(ib, ik), st1%group%psib(ib, ik), conjugate_xx = .false.)
990 call batch_axpy(gr%np, zfact, st1%group%psib(ib, ik), st%group%psib(ib, ik))
991 end do
992 end do
993
994 end do
995 ! End of Taylor expansion loop.
996
997 call states_elec_end(st1)
998 call states_elec_end(hst1)
999
1000 ! We now add the inhomogeneous part, if present.
1001 if (hamiltonian_elec_inh_term(hm)) then
1002 !write(*, *) 'Now we apply the inhomogeneous term...'
1003
1004 call states_elec_copy(st1, hm%inh_st)
1005 call states_elec_copy(hst1, hm%inh_st)
1006
1007
1008 do ik = st%d%kpt%start, st%d%kpt%end
1009 do ib = st%group%block_start, st%group%block_end
1010 call batch_axpy(gr%np, deltat, st1%group%psib(ib, ik), st%group%psib(ib, ik))
1011 end do
1012 end do
1013
1014 zfact = m_one
1015 do i = 1, te%exp_order
1016 zfact = zfact * deltat / (i+1)
1017
1018 if (i == 1) then
1019 call zhamiltonian_elec_apply_all(hm, namespace, gr, hm%inh_st, hst1)
1020 else
1021 call zhamiltonian_elec_apply_all(hm, namespace, gr, st1, hst1)
1022 end if
1023
1024 do ik = st%d%kpt%start, st%d%kpt%end
1025 do ib = st%group%block_start, st%group%block_end
1026 call batch_scal2v(gr%np, -m_zi, hst1%group%psib(ib, ik), st1%group%psib(ib, ik), conjugate_xx = .false.)
1027 call batch_axpy(gr%np, deltat * zfact, st1%group%psib(ib, ik), st%group%psib(ib, ik))
1028 end do
1029 end do
1030
1031 end do
1032
1033 call states_elec_end(st1)
1034 call states_elec_end(hst1)
1035
1036 end if
1037
1038 if (present(order)) order = te%exp_order*st%nik*st%nst ! This should be the correct number
1039
1040 pop_sub(exponential_apply_all)
1041 end subroutine exponential_apply_all
1042
1043 subroutine exponential_apply_phi_batch(te, namespace, mesh, hm, psib, deltat, k, op)
1044 class(exponential_t), intent(inout) :: te
1045 type(namespace_t), intent(in) :: namespace
1046 class(mesh_t), intent(in) :: mesh
1047 class(hamiltonian_abst_t), intent(inout) :: hm
1048 class(batch_t), intent(inout) :: psib
1049 real(real64), intent(in) :: deltat
1050 integer, intent(in) :: k
1051 class(operator_t), target,optional, intent(in) :: op
1052
1053 class(chebyshev_function_t), pointer :: chebyshev_function
1054 complex(real64) :: deltat_
1055 class(operator_t), pointer :: op_
1056
1057 push_sub_with_profile(exponential_apply_phi_batch)
1058
1059 assert(psib%type() == type_cmplx)
1060
1061 if (.not. hm%is_hermitian() .and. te%exp_method == exp_chebyshev) then
1062 write(message(1), '(a)') 'The Chebyshev expansion for the exponential will only converge if the imaginary'
1063 write(message(2), '(a)') 'eigenvalues are small enough compared to the span of the real eigenvalues,'
1064 write(message(3), '(a)') 'i.e., for ratios smaller than about 1e-3.'
1065 write(message(4), '(a)') 'The Lanczos method ("TDExponentialMethod = lanczos") is guaranteed to'
1066 write(message(5), '(a)') 'always converge in this case.'
1067 call messages_warning(5, namespace=namespace)
1068 end if
1069
1070 if (present(op)) then
1071 op_ => op
1072 else
1073 op_ => hamiltonian_operator_t(namespace, mesh, hm)
1074 end if
1075
1076 deltat_ = cmplx(deltat, m_zero, real64)
1077
1078 select case (te%exp_method)
1079 case (exp_taylor)
1080 call exponential_taylor_series_batch(te, namespace, mesh, hm, psib, deltat_, op_, phik_shift=k)
1081
1082 case (exp_lanczos)
1083 if (k == 1) then
1084 call exponential_lanczos_function_batch(te, namespace, mesh, hm, psib, deltat_, phi1, op_)
1085 else if (k == 2) then
1086 call exponential_lanczos_function_batch(te, namespace, mesh, hm, psib, deltat_, phi2, op_)
1087 else
1088 write(message(1), '(a)') 'Lanczos expansion not implemented for phi_k, k > 2'
1089 call messages_fatal(1, namespace=namespace)
1090 end if
1091
1092 case (exp_chebyshev)
1093 if (k == 1) then
1094 chebyshev_function => chebyshev_numerical_t(hm%spectral_half_span, hm%spectral_middle_point, deltat, phi1)
1095 else if (k == 2) then
1096 chebyshev_function => chebyshev_numerical_t(hm%spectral_half_span, hm%spectral_middle_point, deltat, phi2)
1097 else
1098 write(message(1), '(a)') 'Chebyshev expansion not implemented for phi_k, k > 2'
1099 call messages_fatal(1, namespace=namespace)
1100 end if
1101 call exponential_cheby_batch(te, namespace, mesh, hm, psib, chebyshev_function, op_)
1102 deallocate(chebyshev_function)
1103 end select
1104
1105 if (.not.present(op)) then
1106 safe_deallocate_p(op_)
1107 end if
1108
1109 pop_sub_with_profile(exponential_apply_phi_batch)
1110 end subroutine exponential_apply_phi_batch
1111
1112 function hamiltonian_operator_constructor(namespace, mesh, hm) result(this)
1113 type(namespace_t), target, intent(in) :: namespace
1114 class(mesh_t), target, intent(in) :: mesh
1115 class(hamiltonian_abst_t), target, intent(in) :: hm
1116 type(hamiltonian_operator_t), pointer :: this
1117
1119
1120 allocate(this)
1121 call this%init(namespace, mesh, hm)
1122
1125
1126 subroutine hamiltonian_operator_init(this, namespace, mesh, hm)
1127 class(hamiltonian_operator_t), intent(inout) :: this
1128 type(namespace_t), target, intent(in) :: namespace
1129 class(mesh_t), target, intent(in) :: mesh
1130 class(hamiltonian_abst_t), target, intent(in) :: hm
1131
1133
1134 this%mesh => mesh
1135 this%namespace => namespace
1136 this%hm => hm
1137
1139 end subroutine hamiltonian_operator_init
1140
1141 subroutine hamiltonian_operator_apply(this, psib, hpsib)
1142 class(hamiltonian_operator_t), intent(in) :: this
1143 class(batch_t), intent(inout) :: psib
1144 class(batch_t), intent(inout) :: hpsib
1145
1147
1148 call this%hm%zapply(this%namespace, this%mesh, psib, hpsib)
1149
1151 end subroutine hamiltonian_operator_apply
1152
1153end module exponential_oct_m
1154
1155!! Local Variables:
1156!! mode: f90
1157!! coding: utf-8
1158!! End:
batchified version of the BLAS axpy routine:
Definition: batch_ops.F90:159
batchified scale with optional conjugation:
Definition: batch_ops.F90:181
scale a batch by a constant or vector
Definition: batch_ops.F90:167
batchified version of
Definition: batch_ops.F90:187
subroutine, public accel_finish()
Definition: accel.F90:1059
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:178
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)
make a (selective) copy of a states_elec_t object
type(type_t), parameter, public type_cmplx
Definition: types.F90:136
Definition: xc.F90:120
Class defining batches of mesh functions.
Definition: batch.F90:162
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:141
int true(void)