41#include "./base/base_uses.f90"
46 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'negf_integr_cc'
47 LOGICAL,
PARAMETER,
PRIVATE :: debug_this_module = .true.
74 INTEGER :: interval_id = -1
76 INTEGER :: shape_id = -1
78 REAL(kind=
dp) :: error = -1.0_dp
88 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: tnodes
113 SUBROUTINE ccquad_init(cc_env, xnodes, nnodes, a, b, interval_id, shape_id, weights, tnodes_restart)
115 INTEGER,
INTENT(inout) :: nnodes
116 COMPLEX(kind=dp),
DIMENSION(nnodes),
INTENT(out) :: xnodes
117 COMPLEX(kind=dp),
INTENT(in) :: a, b
118 INTEGER,
INTENT(in) :: interval_id, shape_id
120 REAL(kind=
dp),
DIMENSION(nnodes),
INTENT(in), &
121 OPTIONAL :: tnodes_restart
123 CHARACTER(len=*),
PARAMETER :: routinen =
'ccquad_init'
125 INTEGER :: handle, icol, ipoint, irow, ncols, &
127 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :), &
128 POINTER :: w_data, w_data_my
131 CALL timeset(routinen, handle)
136 nnodes = 2*((nnodes - 1)/2) + 1
138 cc_env%interval_id = interval_id
139 cc_env%shape_id = shape_id
142 cc_env%error = huge(0.0_dp)
144 NULLIFY (cc_env%integral, cc_env%error_fm, cc_env%weights)
145 ALLOCATE (cc_env%weights)
146 CALL cp_fm_get_info(weights, local_data=w_data, nrow_local=nrows, ncol_local=ncols, matrix_struct=fm_struct)
153 w_data_my(irow, icol) = abs(w_data(irow, icol))
157 SELECT CASE (interval_id)
159 nnodes_half = nnodes/2 + 1
163 cpabort(
"Unimplemented interval type")
166 ALLOCATE (cc_env%tnodes(nnodes))
168 IF (
PRESENT(tnodes_restart))
THEN
169 cc_env%tnodes(1:nnodes) = tnodes_restart(1:nnodes)
176 IF (nnodes_half > 2)
THEN
180 SELECT CASE (interval_id)
183 DO ipoint = nnodes_half - 1, 1, -1
184 cc_env%tnodes(nnodes_half + ipoint) = -cc_env%tnodes(nnodes_half - ipoint)
188 cc_env%tnodes(1:nnodes_half) = 2.0_dp*cc_env%tnodes(1:nnodes_half) + 1.0_dp
194 CALL timestop(handle)
206 CHARACTER(len=*),
PARAMETER :: routinen =
'ccquad_release'
208 INTEGER :: handle, ipoint
210 CALL timeset(routinen, handle)
212 IF (
ASSOCIATED(cc_env%error_fm))
THEN
214 DEALLOCATE (cc_env%error_fm)
215 NULLIFY (cc_env%error_fm)
218 IF (
ASSOCIATED(cc_env%weights))
THEN
220 DEALLOCATE (cc_env%weights)
221 NULLIFY (cc_env%weights)
224 IF (
ASSOCIATED(cc_env%integral))
THEN
226 DEALLOCATE (cc_env%integral)
227 NULLIFY (cc_env%integral)
230 IF (
ALLOCATED(cc_env%zdata_cache))
THEN
231 DO ipoint =
SIZE(cc_env%zdata_cache), 1, -1
235 DEALLOCATE (cc_env%zdata_cache)
238 IF (
ALLOCATED(cc_env%tnodes))
DEALLOCATE (cc_env%tnodes)
240 CALL timestop(handle)
253 COMPLEX(kind=dp),
ALLOCATABLE,
DIMENSION(:), &
254 INTENT(inout) :: xnodes_next
256 CHARACTER(len=*),
PARAMETER :: routinen =
'ccquad_double_number_of_points'
258 INTEGER :: handle, ipoint, nnodes_exist, &
259 nnodes_half, nnodes_next
260 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: tnodes, tnodes_old
262 CALL timeset(routinen, handle)
264 cpassert(.NOT.
ALLOCATED(xnodes_next))
265 cpassert(
ASSOCIATED(cc_env%integral))
266 cpassert(
ASSOCIATED(cc_env%error_fm))
267 cpassert(
ALLOCATED(cc_env%zdata_cache))
270 nnodes_exist =
SIZE(cc_env%zdata_cache)
273 nnodes_half = nnodes_exist - 1
275 SELECT CASE (cc_env%interval_id)
278 nnodes_next = 2*nnodes_half
280 nnodes_next = nnodes_half
282 cpabort(
"Unimplemented interval type")
285 ALLOCATE (xnodes_next(nnodes_next))
286 ALLOCATE (tnodes(nnodes_next))
289 -0.5_dp/real(nnodes_half, kind=
dp), &
294 SELECT CASE (cc_env%interval_id)
297 DO ipoint = 1, nnodes_half
298 tnodes(nnodes_half + ipoint) = -tnodes(nnodes_half - ipoint + 1)
302 tnodes(1:nnodes_half) = 2.0_dp*tnodes(1:nnodes_half) + 1.0_dp
306 CALL move_alloc(cc_env%tnodes, tnodes_old)
307 nnodes_exist =
SIZE(tnodes_old)
309 ALLOCATE (cc_env%tnodes(nnodes_exist + nnodes_next))
310 cc_env%tnodes(1:nnodes_exist) = tnodes_old(1:nnodes_exist)
311 cc_env%tnodes(nnodes_exist + 1:nnodes_exist + nnodes_next) = tnodes(1:nnodes_next)
312 DEALLOCATE (tnodes_old)
318 CALL timestop(handle)
336 TYPE(
cp_cfm_type),
DIMENSION(:),
INTENT(inout) :: zdata_next
338 CHARACTER(len=*),
PARAMETER :: routinen =
'ccquad_reduce_and_append_zdata'
341 COMPLEX(kind=dp),
ALLOCATABLE,
DIMENSION(:) :: zscale
342 INTEGER :: handle, ipoint, nnodes_exist, &
343 nnodes_half, nnodes_next
344 TYPE(
cp_cfm_type),
ALLOCATABLE,
DIMENSION(:) :: zdata_tmp
346 CALL timeset(routinen, handle)
348 nnodes_next =
SIZE(zdata_next)
349 cpassert(nnodes_next > 0)
352 nnodes_exist =
SIZE(cc_env%tnodes)
353 cpassert(nnodes_exist >= nnodes_next)
355 ALLOCATE (zscale(nnodes_next))
357 cc_env%a, cc_env%b, cc_env%shape_id, weights=zscale)
362 DO ipoint = 1, nnodes_next
368 IF (
ALLOCATED(cc_env%zdata_cache))
THEN
369 nnodes_exist =
SIZE(cc_env%zdata_cache)
374 SELECT CASE (cc_env%interval_id)
376 IF (
ALLOCATED(cc_env%zdata_cache))
THEN
377 cpassert(nnodes_exist == nnodes_next/2 + 1)
378 nnodes_half = nnodes_exist - 1
380 cpassert(mod(nnodes_next, 2) == 1)
381 nnodes_half = nnodes_next/2 + 1
384 IF (
ALLOCATED(cc_env%zdata_cache))
THEN
385 cpassert(nnodes_exist == nnodes_next + 1)
388 nnodes_half = nnodes_next
392 DO ipoint = nnodes_next/2, 1, -1
397 IF (
ALLOCATED(cc_env%zdata_cache))
THEN
399 ALLOCATE (zdata_tmp(nnodes_half + nnodes_exist))
401 DO ipoint = 1, nnodes_half
402 zdata_tmp(2*ipoint - 1) = cc_env%zdata_cache(ipoint)
403 zdata_tmp(2*ipoint) = zdata_next(ipoint)
404 zdata_next(ipoint) = cfm_null
406 zdata_tmp(nnodes_half + nnodes_exist) = cc_env%zdata_cache(nnodes_exist)
408 CALL move_alloc(zdata_tmp, cc_env%zdata_cache)
412 ALLOCATE (cc_env%zdata_cache(nnodes_half))
414 DO ipoint = 1, nnodes_half
415 cc_env%zdata_cache(ipoint) = zdata_next(ipoint)
416 zdata_next(ipoint) = cfm_null
420 CALL timestop(handle)
432 CHARACTER(len=*),
PARAMETER :: routinen =
'ccquad_refine_integral'
434 COMPLEX(kind=dp),
CONTIGUOUS,
DIMENSION(:, :, :), &
435 POINTER :: ztmp, ztmp_dct
436 INTEGER :: handle, icol, ipoint, irow, ncols_local, nintervals, nintervals_half, &
437 nintervals_half_plus_1, nintervals_half_plus_2, nintervals_plus_2, nrows_local, stat
439 REAL(kind=
dp) :: rscale
440 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: weights
446 CALL timeset(routinen, handle)
448 cpassert(
ALLOCATED(cc_env%zdata_cache))
450 nintervals_half_plus_1 =
SIZE(cc_env%zdata_cache)
451 nintervals_half = nintervals_half_plus_1 - 1
452 nintervals_half_plus_2 = nintervals_half_plus_1 + 1
453 nintervals = 2*nintervals_half
454 nintervals_plus_2 = nintervals + 2
455 cpassert(nintervals_half > 1)
457 IF (.NOT.
ASSOCIATED(cc_env%integral))
THEN
462 ALLOCATE (cc_env%integral)
464 NULLIFY (cc_env%error_fm)
465 ALLOCATE (cc_env%error_fm)
469 IF (debug_this_module)
THEN
470 DO ipoint = 1, nintervals_half_plus_1
476 CALL cp_cfm_get_info(cc_env%integral, nrow_local=nrows_local, ncol_local=ncols_local)
478 ALLOCATE (weights(nintervals_half))
481 DO ipoint = 2, nintervals_half
482 rscale = real(2*(ipoint - 1), kind=
dp)
483 weights(ipoint) = 1.0_dp/(1.0_dp - rscale*rscale)
486 rscale = real(nintervals, kind=
dp)
487 weights(1) = 1.0_dp/(1.0_dp - rscale*rscale)
490 rscale = 1.0_dp/rscale
492 CALL fft_alloc(ztmp, [nintervals, nrows_local, ncols_local])
493 CALL fft_alloc(ztmp_dct, [nintervals, nrows_local, ncols_local])
497 DO icol = 1, ncols_local
498 DO irow = 1, nrows_local
499 DO ipoint = 1, nintervals_half_plus_1
500 ztmp(ipoint, irow, icol) = cc_env%zdata_cache(ipoint)%local_data(irow, icol)
503 DO ipoint = 2, nintervals_half
504 ztmp(nintervals_half + ipoint, irow, icol) = ztmp(nintervals_half_plus_2 - ipoint, irow, icol)
510 CALL fft_fw1d(nintervals, nrows_local*ncols_local, .false., ztmp, ztmp_dct, 1.0_dp, stat)
512 CALL cp_abort(__location__, &
513 "An FFT library is required for Clenshaw-Curtis quadrature. "// &
514 "You can use an alternative integration method instead.")
520 DO icol = 1, ncols_local
521 DO irow = 1, nrows_local
522 ztmp_dct(1, irow, icol) = 0.5_dp*ztmp_dct(1, irow, icol)
523 DO ipoint = 2, nintervals_half
524 ztmp_dct(ipoint, irow, icol) = 0.5_dp*weights(ipoint)*(ztmp_dct(ipoint, irow, icol) + &
525 ztmp_dct(nintervals_plus_2 - ipoint, irow, icol))
527 ztmp_dct(nintervals_half_plus_1, irow, icol) = weights(1)*ztmp_dct(nintervals_half_plus_1, irow, icol)
529 cc_env%integral%local_data(irow, icol) = rscale*
accurate_sum(ztmp_dct(1:nintervals_half_plus_1, irow, icol))
530 cc_env%error_fm%local_data(irow, icol) = rscale*abs(ztmp_dct(nintervals_half_plus_1, irow, icol))
535 CALL fft_dealloc(ztmp)
536 CALL fft_dealloc(ztmp_dct)
538 CALL cp_fm_trace(cc_env%error_fm, cc_env%weights, cc_env%error)
541 CALL timestop(handle)
Basic linear algebra operations for complex full matrices.
subroutine, public cp_cfm_scale_and_add(alpha, matrix_a, beta, matrix_b)
Scale and add two BLACS matrices (a = alpha*a + beta*b).
Represents a complex full matrix distributed on many processors.
subroutine, public cp_cfm_release(matrix)
Releases a full matrix.
subroutine, public cp_cfm_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
Creates a new full matrix with the given structure.
subroutine, public cp_cfm_get_info(matrix, name, nrow_global, ncol_global, nrow_block, ncol_block, nrow_local, ncol_local, row_indices, col_indices, local_data, context, matrix_struct, para_env)
Returns information about a full matrix.
Basic linear algebra operations for full matrices.
represent the structure of a full matrix
logical function, public cp_fm_struct_equivalent(fmstruct1, fmstruct2)
returns true if the two matrix structures are equivalent, false otherwise.
represent a full matrix distributed on many processors
subroutine, public cp_fm_get_info(matrix, name, nrow_global, ncol_global, nrow_block, ncol_block, nrow_local, ncol_local, row_indices, col_indices, local_data, context, nrow_locals, ncol_locals, matrix_struct, para_env)
returns all kind of information about the full matrix
subroutine, public cp_fm_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
creates a new full matrix with the given structure
sums arrays of real/complex numbers with much reduced round-off as compared to a naive implementation...
Defines the basic variable types.
integer, parameter, public int_8
integer, parameter, public dp
Definition of mathematical constants and functions.
complex(kind=dp), parameter, public z_one
complex(kind=dp), parameter, public z_zero
Adaptive Clenshaw-Curtis quadrature algorithm to integrate a complex-valued function in a complex pla...
integer, parameter, public cc_shape_linear
subroutine, public ccquad_refine_integral(cc_env)
Refine approximated integral.
integer, parameter, public cc_interval_full
subroutine, public ccquad_double_number_of_points(cc_env, xnodes_next)
Get the next set of points at which the integrand needs to be computed. These points are then can be ...
subroutine, public ccquad_release(cc_env)
Release a Clenshaw-Curtis quadrature environment variable.
integer, parameter, public cc_interval_half
subroutine, public ccquad_init(cc_env, xnodes, nnodes, a, b, interval_id, shape_id, weights, tnodes_restart)
Initialise a Clenshaw-Curtis quadrature environment variable.
integer, parameter, public cc_shape_arc
subroutine, public ccquad_reduce_and_append_zdata(cc_env, zdata_next)
Prepare Clenshaw-Curtis environment for the subsequent refinement of the integral.
Helper functions for integration routines.
subroutine, public rescale_normalised_nodes(nnodes, tnodes, a, b, shape_id, xnodes, weights)
subroutine, public rescale_nodes_cos(nnodes, tnodes)
Rescale nodes tnodes(i) = cos(pi/2 * (1-tnodes(i))); tnodes \in [-1 .. 1] .
integer, parameter, public contour_shape_arc
integer, parameter, public contour_shape_linear
Represent a complex full matrix.
keeps the information about the structure of a full matrix
Adaptive Clenshaw-Curtis environment.