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