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)