(git:98357aa)
Loading...
Searching...
No Matches
negf_integr_cc.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \brief Adaptive Clenshaw-Curtis quadrature algorithm to integrate a complex-valued function in
10!> a complex plane
11!> \par History
12!> * 05.2017 created [Sergey Chulkov]
13! **************************************************************************************************
17 USE cp_cfm_types, ONLY: cp_cfm_create,&
24 USE cp_fm_types, ONLY: cp_fm_create,&
28 USE fft_tools, ONLY: fft_alloc,&
29 fft_dealloc,&
31 USE kahan_sum, ONLY: accurate_sum
32 USE kinds, ONLY: dp,&
33 int_8
34 USE mathconstants, ONLY: z_one,&
35 z_zero
41#include "./base/base_uses.f90"
42
43 IMPLICIT NONE
44 PRIVATE
45
46 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'negf_integr_cc'
47 LOGICAL, PARAMETER, PRIVATE :: debug_this_module = .true.
48
49 INTEGER, PARAMETER, PUBLIC :: cc_interval_full = 0, &
51
52 INTEGER, PARAMETER, PUBLIC :: cc_shape_linear = contour_shape_linear, &
54
55 PUBLIC :: ccquad_type
56
57 PUBLIC :: ccquad_init, &
62
63! **************************************************************************************************
64!> \brief Adaptive Clenshaw-Curtis environment.
65! **************************************************************************************************
67 !> integration lower and upper bounds
68 COMPLEX(kind=dp) :: a = z_zero, b = z_zero
69 !> integration interval:
70 !> cc_interval_full -- [a .. b],
71 !> grid density: 'a' .. . . . . . .. 'b';
72 !> cc_interval_half -- [a .. 2b-a], assuming int_{b}^{2b-a} f(x) dx = 0,
73 !> grid density: 'a' .. . . . 'b'
74 INTEGER :: interval_id = -1
75 !> integration shape
76 INTEGER :: shape_id = -1
77 !> estimated error
78 REAL(kind=dp) :: error = -1.0_dp
79 !> approximate integral value
80 TYPE(cp_cfm_type), POINTER :: integral => null()
81 !> error estimate for every element of the 'integral' matrix
82 TYPE(cp_fm_type), POINTER :: error_fm => null()
83 !> weights associated with matrix elements; the 'error' variable contains the value Trace(error_fm * weights)
84 TYPE(cp_fm_type), POINTER :: weights => null()
85 !> integrand value at grid points. Due to symmetry of Clenshaw-Curtis quadratures,
86 !> we only need to keep the left half-interval
87 TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:) :: zdata_cache
88 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: tnodes
89 END TYPE ccquad_type
90
91CONTAINS
92
93! **************************************************************************************************
94!> \brief Initialise a Clenshaw-Curtis quadrature environment variable.
95!> \param cc_env environment variable to initialise
96!> \param xnodes points at which an integrand needs to be computed (initialised on exit)
97!> \param nnodes initial number of points to compute (initialised on exit)
98!> \param a integral lower bound
99!> \param b integral upper bound
100!> \param interval_id full [-1 .. 1] or half [-1 .. 0] interval
101!> \param shape_id shape of a curve along which the integral will be evaluated
102!> \param weights weights associated with matrix elements; used to compute cumulative error
103!> \param tnodes_restart list of nodes over the interval [-1 .. 1] from a previous integral evaluation.
104!> If present, the same set of 'xnodes' will be used to compute this integral.
105!> \par History
106!> * 05.2017 created [Sergey Chulkov]
107!> \note Clenshaw-Curtis quadratures are defined on the interval [-1 .. 1] and have non-uniforms node
108!> distribution which is symmetric and much sparse about 0. When the half-interval [-1 .. 0]
109!> is requested, the integrand value on another subinterval (0 .. 1] is assumed to be zero.
110!> Half interval mode is typically useful for rapidly decaying integrands (e.g. multiplied by
111!> Fermi function), so we do not actually need a fine grid spacing on this tail.
112! **************************************************************************************************
113 SUBROUTINE ccquad_init(cc_env, xnodes, nnodes, a, b, interval_id, shape_id, weights, tnodes_restart)
114 TYPE(ccquad_type), INTENT(out) :: cc_env
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
119 TYPE(cp_fm_type), INTENT(IN) :: weights
120 REAL(kind=dp), DIMENSION(nnodes), INTENT(in), &
121 OPTIONAL :: tnodes_restart
122
123 CHARACTER(len=*), PARAMETER :: routinen = 'ccquad_init'
124
125 INTEGER :: handle, icol, ipoint, irow, ncols, &
126 nnodes_half, nrows
127 REAL(kind=dp), CONTIGUOUS, DIMENSION(:, :), &
128 POINTER :: w_data, w_data_my
129 TYPE(cp_fm_struct_type), POINTER :: fm_struct
130
131 CALL timeset(routinen, handle)
132
133 cpassert(nnodes > 2)
134
135 ! ensure that MOD(nnodes-1, 2) == 0
136 nnodes = 2*((nnodes - 1)/2) + 1
137
138 cc_env%interval_id = interval_id
139 cc_env%shape_id = shape_id
140 cc_env%a = a
141 cc_env%b = b
142 cc_env%error = huge(0.0_dp)
143
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)
147 CALL cp_fm_create(cc_env%weights, fm_struct)
148 CALL cp_fm_get_info(cc_env%weights, local_data=w_data_my)
149
150 ! use the explicit loop to avoid temporary arrays
151 DO icol = 1, ncols
152 DO irow = 1, nrows
153 w_data_my(irow, icol) = abs(w_data(irow, icol))
154 END DO
155 END DO
156
157 SELECT CASE (interval_id)
158 CASE (cc_interval_full)
159 nnodes_half = nnodes/2 + 1
160 CASE (cc_interval_half)
161 nnodes_half = nnodes
162 CASE DEFAULT
163 cpabort("Unimplemented interval type")
164 END SELECT
165
166 ALLOCATE (cc_env%tnodes(nnodes))
167
168 IF (PRESENT(tnodes_restart)) THEN
169 cc_env%tnodes(1:nnodes) = tnodes_restart(1:nnodes)
170 ELSE
171 CALL equidistant_nodes_a_b(-1.0_dp, 0.0_dp, nnodes_half, cc_env%tnodes)
172
173 ! rescale all but the end-points, as they are transformed into themselves (-1.0 -> -1.0; 0.0 -> 0.0).
174 ! Moreover, by applying this rescaling transformation to the end-points we cannot guarantee the exact
175 ! result due to rounding errors in evaluation of COS function.
176 IF (nnodes_half > 2) THEN
177 CALL rescale_nodes_cos(nnodes_half - 2, cc_env%tnodes(2:))
178 END IF
179
180 SELECT CASE (interval_id)
181 CASE (cc_interval_full)
182 ! reflect symmetric nodes
183 DO ipoint = nnodes_half - 1, 1, -1
184 cc_env%tnodes(nnodes_half + ipoint) = -cc_env%tnodes(nnodes_half - ipoint)
185 END DO
186 CASE (cc_interval_half)
187 ! rescale half-interval : [-1 .. 0] -> [-1 .. 1]
188 cc_env%tnodes(1:nnodes_half) = 2.0_dp*cc_env%tnodes(1:nnodes_half) + 1.0_dp
189 END SELECT
190 END IF
191
192 CALL rescale_normalised_nodes(nnodes, cc_env%tnodes, a, b, shape_id, xnodes)
193
194 CALL timestop(handle)
195 END SUBROUTINE ccquad_init
196
197! **************************************************************************************************
198!> \brief Release a Clenshaw-Curtis quadrature environment variable.
199!> \param cc_env environment variable to release (modified on exit)
200!> \par History
201!> * 05.2017 created [Sergey Chulkov]
202! **************************************************************************************************
203 SUBROUTINE ccquad_release(cc_env)
204 TYPE(ccquad_type), INTENT(inout) :: cc_env
205
206 CHARACTER(len=*), PARAMETER :: routinen = 'ccquad_release'
207
208 INTEGER :: handle, ipoint
209
210 CALL timeset(routinen, handle)
211
212 IF (ASSOCIATED(cc_env%error_fm)) THEN
213 CALL cp_fm_release(cc_env%error_fm)
214 DEALLOCATE (cc_env%error_fm)
215 NULLIFY (cc_env%error_fm)
216 END IF
217
218 IF (ASSOCIATED(cc_env%weights)) THEN
219 CALL cp_fm_release(cc_env%weights)
220 DEALLOCATE (cc_env%weights)
221 NULLIFY (cc_env%weights)
222 END IF
223
224 IF (ASSOCIATED(cc_env%integral)) THEN
225 CALL cp_cfm_release(cc_env%integral)
226 DEALLOCATE (cc_env%integral)
227 NULLIFY (cc_env%integral)
228 END IF
229
230 IF (ALLOCATED(cc_env%zdata_cache)) THEN
231 DO ipoint = SIZE(cc_env%zdata_cache), 1, -1
232 CALL cp_cfm_release(cc_env%zdata_cache(ipoint))
233 END DO
234
235 DEALLOCATE (cc_env%zdata_cache)
236 END IF
237
238 IF (ALLOCATED(cc_env%tnodes)) DEALLOCATE (cc_env%tnodes)
239
240 CALL timestop(handle)
241 END SUBROUTINE ccquad_release
242
243! **************************************************************************************************
244!> \brief Get the next set of points at which the integrand needs to be computed. These points are
245!> then can be used to refine the integral approximation.
246!> \param cc_env environment variable (modified on exit)
247!> \param xnodes_next set of additional points (allocated and initialised on exit)
248!> \par History
249!> * 05.2017 created [Sergey Chulkov]
250! **************************************************************************************************
251 SUBROUTINE ccquad_double_number_of_points(cc_env, xnodes_next)
252 TYPE(ccquad_type), INTENT(inout) :: cc_env
253 COMPLEX(kind=dp), ALLOCATABLE, DIMENSION(:), &
254 INTENT(inout) :: xnodes_next
255
256 CHARACTER(len=*), PARAMETER :: routinen = 'ccquad_double_number_of_points'
257
258 INTEGER :: handle, ipoint, nnodes_exist, &
259 nnodes_half, nnodes_next
260 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: tnodes, tnodes_old
261
262 CALL timeset(routinen, handle)
263
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))
268
269 ! due to symmetry of Clenshaw-Curtis quadratures, we only need to keep the left half-interval [-1 .. 0]
270 nnodes_exist = SIZE(cc_env%zdata_cache)
271 ! new nodes will be placed between the existed ones, so the number of nodes
272 ! on the left half-interval [-1 .. 0] is equal to nnodes_exist - 1
273 nnodes_half = nnodes_exist - 1
274
275 SELECT CASE (cc_env%interval_id)
276 CASE (cc_interval_full)
277 ! double number of nodes as we have 2 half-intervals [-1 .. 0] and [0 .. 1]
278 nnodes_next = 2*nnodes_half
279 CASE (cc_interval_half)
280 nnodes_next = nnodes_half
281 CASE DEFAULT
282 cpabort("Unimplemented interval type")
283 END SELECT
284
285 ALLOCATE (xnodes_next(nnodes_next))
286 ALLOCATE (tnodes(nnodes_next))
287
288 CALL equidistant_nodes_a_b(0.5_dp/real(nnodes_half, kind=dp) - 1.0_dp, &
289 -0.5_dp/real(nnodes_half, kind=dp), &
290 nnodes_half, tnodes)
291
292 CALL rescale_nodes_cos(nnodes_half, tnodes)
293
294 SELECT CASE (cc_env%interval_id)
295 CASE (cc_interval_full)
296 ! reflect symmetric nodes
297 DO ipoint = 1, nnodes_half
298 tnodes(nnodes_half + ipoint) = -tnodes(nnodes_half - ipoint + 1)
299 END DO
300 CASE (cc_interval_half)
301 ! rescale half-interval : [-1 .. 0] -> [-1 .. 1]
302 tnodes(1:nnodes_half) = 2.0_dp*tnodes(1:nnodes_half) + 1.0_dp
303 END SELECT
304
305 ! append new tnodes to the cache
306 CALL move_alloc(cc_env%tnodes, tnodes_old)
307 nnodes_exist = SIZE(tnodes_old)
308
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)
313
314 ! rescale nodes [-1 .. 1] -> [a .. b] according to the shape
315 CALL rescale_normalised_nodes(nnodes_next, tnodes, cc_env%a, cc_env%b, cc_env%shape_id, xnodes_next)
316
317 DEALLOCATE (tnodes)
318 CALL timestop(handle)
319 END SUBROUTINE ccquad_double_number_of_points
320
321! **************************************************************************************************
322!> \brief Prepare Clenshaw-Curtis environment for the subsequent refinement of the integral.
323!> \param cc_env environment variable (modified on exit)
324!> \param zdata_next additional integrand value at additional points (modified on exit)
325!> \par History
326!> * 05.2017 created [Sergey Chulkov]
327!> \note Due to symmetry of Clenshaw-Curtis quadratures (weight(x) == weight(-x)), we do not need to
328!> keep all the matrices from 'zdata_next', only 'zdata_next(x) + zdata_next(-x)' is needed.
329!> In order to reduce the number of matrix allocations, we move some of the matrices from the
330!> end of the 'zdata_new' array to the 'cc_env%zdata_cache' array, and nullify the corresponding
331!> pointers at 'zdata_next' array. So the calling subroutine need to release the remained
332!> matrices or reuse them but taking into account the missed ones.
333! **************************************************************************************************
334 SUBROUTINE ccquad_reduce_and_append_zdata(cc_env, zdata_next)
335 TYPE(ccquad_type), INTENT(inout) :: cc_env
336 TYPE(cp_cfm_type), DIMENSION(:), INTENT(inout) :: zdata_next
337
338 CHARACTER(len=*), PARAMETER :: routinen = 'ccquad_reduce_and_append_zdata'
339 TYPE(cp_cfm_type), PARAMETER :: cfm_null = cp_cfm_type()
340
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
345
346 CALL timeset(routinen, handle)
347
348 nnodes_next = SIZE(zdata_next)
349 cpassert(nnodes_next > 0)
350
351 ! compute weights of new points on a complex contour according to their values of the 't' parameter
352 nnodes_exist = SIZE(cc_env%tnodes)
353 cpassert(nnodes_exist >= nnodes_next)
354
355 ALLOCATE (zscale(nnodes_next))
356 CALL rescale_normalised_nodes(nnodes_next, cc_env%tnodes(nnodes_exist - nnodes_next + 1:nnodes_exist), &
357 cc_env%a, cc_env%b, cc_env%shape_id, weights=zscale)
358
359 IF (cc_env%interval_id == cc_interval_half) zscale(:) = 2.0_dp*zscale(:)
360
361 ! rescale integrand values
362 DO ipoint = 1, nnodes_next
363 CALL cp_cfm_scale(zscale(ipoint), zdata_next(ipoint))
364 END DO
365 DEALLOCATE (zscale)
366
367 ! squash points with the same clenshaw-curtis weights together
368 IF (ALLOCATED(cc_env%zdata_cache)) THEN
369 nnodes_exist = SIZE(cc_env%zdata_cache)
370 ELSE
371 nnodes_exist = 0
372 END IF
373
374 SELECT CASE (cc_env%interval_id)
375 CASE (cc_interval_full)
376 IF (ALLOCATED(cc_env%zdata_cache)) THEN
377 cpassert(nnodes_exist == nnodes_next/2 + 1)
378 nnodes_half = nnodes_exist - 1
379 ELSE
380 cpassert(mod(nnodes_next, 2) == 1)
381 nnodes_half = nnodes_next/2 + 1
382 END IF
383 CASE (cc_interval_half)
384 IF (ALLOCATED(cc_env%zdata_cache)) THEN
385 cpassert(nnodes_exist == nnodes_next + 1)
386 END IF
387
388 nnodes_half = nnodes_next
389 END SELECT
390
391 IF (cc_env%interval_id == cc_interval_full) THEN
392 DO ipoint = nnodes_next/2, 1, -1
393 CALL cp_cfm_scale_and_add(z_one, zdata_next(ipoint), z_one, zdata_next(nnodes_next - ipoint + 1))
394 END DO
395 END IF
396
397 IF (ALLOCATED(cc_env%zdata_cache)) THEN
398 ! note that nnodes_half+1 == nnodes_exist for both half- and full-intervals
399 ALLOCATE (zdata_tmp(nnodes_half + nnodes_exist))
400
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
405 END DO
406 zdata_tmp(nnodes_half + nnodes_exist) = cc_env%zdata_cache(nnodes_exist)
407
408 CALL move_alloc(zdata_tmp, cc_env%zdata_cache)
409 ELSE
410 CALL cp_cfm_scale(2.0_dp, zdata_next(nnodes_half))
411
412 ALLOCATE (cc_env%zdata_cache(nnodes_half))
413
414 DO ipoint = 1, nnodes_half
415 cc_env%zdata_cache(ipoint) = zdata_next(ipoint)
416 zdata_next(ipoint) = cfm_null
417 END DO
418 END IF
419
420 CALL timestop(handle)
421 END SUBROUTINE ccquad_reduce_and_append_zdata
422
423! **************************************************************************************************
424!> \brief Refine approximated integral.
425!> \param cc_env environment variable (modified on exit)
426!> \par History
427!> * 05.2017 created [Sergey Chulkov]
428! **************************************************************************************************
429 SUBROUTINE ccquad_refine_integral(cc_env)
430 TYPE(ccquad_type), INTENT(inout) :: cc_env
431
432 CHARACTER(len=*), PARAMETER :: routinen = 'ccquad_refine_integral'
433
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
438 LOGICAL :: equiv
439 REAL(kind=dp) :: rscale
440 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: weights
441 TYPE(cp_fm_struct_type), POINTER :: fm_struct
442
443! TYPE(fft_plan_type) :: fft_plan
444! INTEGER(kind=int_8) :: plan
445
446 CALL timeset(routinen, handle)
447
448 cpassert(ALLOCATED(cc_env%zdata_cache))
449
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)
456
457 IF (.NOT. ASSOCIATED(cc_env%integral)) THEN
458 CALL cp_cfm_get_info(cc_env%zdata_cache(1), matrix_struct=fm_struct)
459 equiv = cp_fm_struct_equivalent(fm_struct, cc_env%weights%matrix_struct)
460 cpassert(equiv)
461
462 ALLOCATE (cc_env%integral)
463 CALL cp_cfm_create(cc_env%integral, fm_struct)
464 NULLIFY (cc_env%error_fm)
465 ALLOCATE (cc_env%error_fm)
466 CALL cp_fm_create(cc_env%error_fm, fm_struct)
467 END IF
468
469 IF (debug_this_module) THEN
470 DO ipoint = 1, nintervals_half_plus_1
471 equiv = cp_fm_struct_equivalent(cc_env%zdata_cache(ipoint)%matrix_struct, cc_env%integral%matrix_struct)
472 cpassert(equiv)
473 END DO
474 END IF
475
476 CALL cp_cfm_get_info(cc_env%integral, nrow_local=nrows_local, ncol_local=ncols_local)
477
478 ALLOCATE (weights(nintervals_half))
479
480 ! omit the trivial weights(1) = 0.5
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)
484 END DO
485 ! weights(1) <- weights(intervals_half + 1)
486 rscale = real(nintervals, kind=dp)
487 weights(1) = 1.0_dp/(1.0_dp - rscale*rscale)
488
489 ! 1.0 / nintervals
490 rscale = 1.0_dp/rscale
491
492 CALL fft_alloc(ztmp, [nintervals, nrows_local, ncols_local])
493 CALL fft_alloc(ztmp_dct, [nintervals, nrows_local, ncols_local])
494
495!$OMP PARALLEL DO DEFAULT(NONE), PRIVATE(icol, ipoint, irow), &
496!$OMP SHARED(cc_env, ncols_local, nintervals_half, nintervals_half_plus_1, nintervals_half_plus_2, nrows_local, ztmp)
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)
501 END DO
502
503 DO ipoint = 2, nintervals_half
504 ztmp(nintervals_half + ipoint, irow, icol) = ztmp(nintervals_half_plus_2 - ipoint, irow, icol)
505 END DO
506 END DO
507 END DO
508!$OMP END PARALLEL DO
509
510 CALL fft_fw1d(nintervals, nrows_local*ncols_local, .false., ztmp, ztmp_dct, 1.0_dp, stat)
511 IF (stat /= 0) THEN
512 CALL cp_abort(__location__, &
513 "An FFT library is required for Clenshaw-Curtis quadrature. "// &
514 "You can use an alternative integration method instead.")
515 END IF
516
517!$OMP PARALLEL DO DEFAULT(NONE), PRIVATE(icol, ipoint, irow), &
518!$OMP SHARED(cc_env, rscale, ncols_local, nintervals_half, nintervals_half_plus_1, nintervals_plus_2), &
519!$OMP SHARED(nrows_local, weights, ztmp_dct)
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))
526 END DO
527 ztmp_dct(nintervals_half_plus_1, irow, icol) = weights(1)*ztmp_dct(nintervals_half_plus_1, irow, icol)
528
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))
531 END DO
532 END DO
533!$OMP END PARALLEL DO
534
535 CALL fft_dealloc(ztmp)
536 CALL fft_dealloc(ztmp_dct)
537
538 CALL cp_fm_trace(cc_env%error_fm, cc_env%weights, cc_env%error)
539
540 DEALLOCATE (weights)
541 CALL timestop(handle)
542 END SUBROUTINE ccquad_refine_integral
543
544END MODULE negf_integr_cc
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
Definition cp_fm_types.F:15
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
subroutine, public fft_fw1d(n, m, trans, zin, zout, scale, stat)
Performs m 1-D forward FFT-s of size n.
Definition fft_tools.F:331
sums arrays of real/complex numbers with much reduced round-off as compared to a naive implementation...
Definition kahan_sum.F:29
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public int_8
Definition kinds.F:54
integer, parameter, public dp
Definition kinds.F:34
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
represent a full matrix
Adaptive Clenshaw-Curtis environment.