26  use, 
intrinsic :: iso_c_binding
 
   27  use, 
intrinsic :: iso_fortran_env
 
   44    real(real64) :: half_span
 
   45    real(real64) :: middle_point
 
   46    real(real64) :: deltat
 
   48    procedure(chebyshev_get_coefficients), 
deferred :: get_coefficients
 
   49    procedure(chebyshev_get_error), 
deferred :: get_error
 
   58      class(chebyshev_function_t),  
intent(in)  :: this
 
   59      integer,                      
intent(in)  :: order
 
   60      complex(real64), 
allocatable, 
intent(out) :: coefficients(:)
 
   63    real(real64) function chebyshev_get_error(this, order)
 
   67      class(chebyshev_function_t),  
intent(in)  :: this
 
   68      integer,      
intent(in)  :: order
 
   80    procedure chebyshev_exp_constructor
 
   91    procedure chebyshev_exp_imagtime_constructor
 
   99      complex(real64), 
intent(in) :: z
 
  105    procedure(complex_function_i), 
pointer, 
nopass :: complex_function
 
  112    procedure chebyshev_numerical_constructor
 
  118    class(chebyshev_function_t), 
intent(inout) :: this
 
  119    real(real64),                
intent(in)    :: half_span
 
  120    real(real64),                
intent(in)    :: middle_point
 
  121    real(real64),                
intent(in)    :: deltat
 
  125    this%half_span = half_span
 
  126    this%middle_point = middle_point
 
  133    class(chebyshev_exp_t), 
pointer    :: chebyshev_function
 
  134    real(real64),           
intent(in) :: half_span
 
  135    real(real64),           
intent(in) :: middle_point
 
  136    real(real64),           
intent(in) :: deltat
 
  140    allocate(chebyshev_function)
 
  141    call chebyshev_function%set_parameters(half_span, middle_point, deltat)
 
  148    integer,                      
intent(in)  :: order
 
  149    complex(real64), 
allocatable, 
intent(out) :: coefficients(:)
 
  154    safe_allocate(coefficients(0:order))
 
  156      coefficients(i) = 
exp(-m_zi*this%middle_point*this%deltat) * &
 
  157        (-m_zi)**i * m_two * loct_bessel(i, this%half_span*this%deltat)
 
  159    coefficients(0) = coefficients(0) / m_two
 
  166    class(chebyshev_exp_t), 
intent(in)  :: this
 
  167    integer,                
intent(in)  :: order
 
  169    real(real64) :: r, inv_r
 
  172    if (order >= this%half_span*this%deltat) 
then 
  173      r = m_two*(order+1)/abs(this%half_span*this%deltat)
 
  175      chebyshev_exp_error = m_two*inv_r**(order+1)/(m_one - inv_r) * 
exp(abs(this%half_span*this%deltat)*(r-inv_r)/m_two)
 
  184    real(real64),                    
intent(in) :: half_span
 
  185    real(real64),                    
intent(in) :: middle_point
 
  186    real(real64),                    
intent(in) :: deltat
 
  190    allocate(chebyshev_function)
 
  191    call chebyshev_function%set_parameters(half_span, middle_point, deltat)
 
  197    class(chebyshev_exp_imagtime_t), 
intent(in)  :: this
 
  198    integer,                         
intent(in)  :: order
 
  199    complex(real64), 
allocatable,    
intent(out) :: coefficients(:)
 
  204    safe_allocate(coefficients(0:order))
 
  206      coefficients(i) = 
exp(-this%middle_point*this%deltat) * &
 
  207        m_two * loct_bessel_in(i, -this%half_span*this%deltat)
 
  209    coefficients(0) = coefficients(0) / m_two
 
  217  real(real64) function chebyshev_exp_imagtime_error(this, order)
 
  219    integer,                         
intent(in)  :: order
 
  221    real(real64) :: upper_bound, lower_bound
 
  222    real(real64), 
parameter :: b = 0.618, d = 0.438
 
  225    upper_bound = this%half_span+this%middle_point
 
  226    lower_bound = -this%half_span+this%middle_point
 
  227    if (order <= upper_bound*this%deltat) 
then 
  229        (m_one+
sqrt(upper_bound*this%deltat*m_pi/(m_four*b))) + m_two*d**(upper_bound*this%deltat)/(m_one-d)
 
  238    real(real64),                  
intent(in) :: half_span
 
  239    real(real64),                  
intent(in) :: middle_point
 
  240    real(real64),                  
intent(in) :: deltat
 
  245    allocate(chebyshev_function)
 
  246    call chebyshev_function%set_parameters(half_span, middle_point, deltat)
 
  247    chebyshev_function%complex_function => complex_function
 
  256    integer,                      
intent(in)  :: order
 
  257    complex(real64), 
allocatable, 
intent(out) :: coefficients(:)
 
  260    complex(real64) :: 
values(0:order)
 
  261    real(real64) :: re_values(0:order), im_values(0:order)
 
  262    real(real64) :: re_coefficients(0:order), im_coefficients(0:order)
 
  263    real(real64) :: theta
 
  267    safe_allocate(coefficients(0:order))
 
  271      values(i) = this%complex_function(-m_zi*this%deltat*(this%half_span*
cos(theta)+this%middle_point))
 
  272      re_values(i) = real(
values(i), real64)
 
  273      im_values(i) = aimag(
values(i))
 
  275    plan = fftw_plan_r2r_1d(order+1, re_values, re_coefficients, fftw_redft00, fftw_estimate)
 
  276    call fftw_execute_r2r(plan, re_values, re_coefficients)
 
  277    call fftw_execute_r2r(plan, im_values, im_coefficients)
 
  278    call fftw_destroy_plan(plan)
 
  281      coefficients(i) = cmplx(re_coefficients(i), im_coefficients(i), real64)/order
 
  284    coefficients(0) = coefficients(0) / m_two
 
  285    coefficients(order) = coefficients(order) / m_two
 
  292  real(real64) function chebyshev_numerical_error(this, order)
 
  294    integer,                      
intent(in)  :: order
 
  297    real(real64) :: inv_r
 
  300    if (order >= this%half_span*this%deltat) 
then 
  301      r = m_two*order/abs(this%half_span*this%deltat)
 
  304        real(this%complex_function(cmplx(abs(this%half_span*this%deltat)*(r-inv_r)/M_TWO, M_ZERO, real64)), real64)
 
double exp(double __x) __attribute__((__nothrow__
 
double sqrt(double __x) __attribute__((__nothrow__
 
double cos(double __x) __attribute__((__nothrow__
 
class(chebyshev_numerical_t) function, pointer chebyshev_numerical_constructor(half_span, middle_point, deltat, complex_function)
 
class(chebyshev_exp_t) function, pointer chebyshev_exp_constructor(half_span, middle_point, deltat)
 
real(real64) function chebyshev_exp_error(this, order)
Use the error estimate from Lubich, C. From Quantum to Classical Molecular Dynamics: Reduced Models a...
 
class(chebyshev_exp_imagtime_t) function, pointer chebyshev_exp_imagtime_constructor(half_span, middle_point, deltat)
 
subroutine chebyshev_numerical_coefficients(this, order, coefficients)
use a discrete cosine transform to compute the coefficients because no analytical formula is availabl...
 
subroutine chebyshev_set_parameters(this, half_span, middle_point, deltat)
 
real(real64) function chebyshev_numerical_error(this, order)
use the error estimate from Lubich, C. From Quantum to Classical Molecular Dynamics: Reduced Models a...
 
subroutine chebyshev_exp_coefficients(this, order, coefficients)
 
subroutine chebyshev_exp_imagtime_coefficients(this, order, coefficients)
 
real(real64) function chebyshev_exp_imagtime_error(this, order)
Use the error estimate from Hochbruck, M. & Ostermann, A. Exponential integrators....
 
This module is intended to contain "only mathematical" functions and procedures.
 
real(real64) function values(xx)