32 equidistant_nodes_a_b,&
35 #include "./base/base_uses.f90"
40 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'negf_integr_simpson'
44 LOGICAL,
PARAMETER,
PRIVATE :: is_boole = .false.
49 PUBLIC :: simpsonrule_type
55 TYPE simpsonrule_subinterval_type
57 REAL(kind=
dp) :: lb, ub
61 REAL(kind=
dp) :: error
63 TYPE(cp_cfm_type) :: fa, fb, fc, fd, fe
64 END TYPE simpsonrule_subinterval_type
71 COMPLEX(kind=dp) :: a, b
78 REAL(kind=
dp) :: error, error_conv
80 TYPE(cp_cfm_type),
POINTER :: integral
82 TYPE(cp_cfm_type),
POINTER :: integral_conv
84 TYPE(cp_cfm_type),
POINTER :: integral_abc, integral_cde, integral_ace
86 TYPE(cp_fm_type),
POINTER :: error_fm
88 TYPE(cp_fm_type),
POINTER :: weights
90 TYPE(simpsonrule_subinterval_type),
ALLOCATABLE, &
91 DIMENSION(:) :: subintervals
95 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: tnodes
96 END TYPE simpsonrule_type
98 COMPLEX(kind=dp),
PARAMETER,
PRIVATE :: z_four = 4.0_dp*
z_one
120 SUBROUTINE simpsonrule_init(sr_env, xnodes, nnodes, a, b, shape_id, conv, weights, tnodes_restart)
121 TYPE(simpsonrule_type),
INTENT(out) :: sr_env
122 INTEGER,
INTENT(inout) :: nnodes
123 COMPLEX(kind=dp),
DIMENSION(nnodes),
INTENT(out) :: xnodes
124 COMPLEX(kind=dp),
INTENT(in) :: a, b
125 INTEGER,
INTENT(in) :: shape_id
126 REAL(kind=
dp),
INTENT(in) :: conv
127 TYPE(cp_fm_type),
INTENT(IN) :: weights
128 REAL(kind=
dp),
DIMENSION(nnodes),
INTENT(in), &
129 OPTIONAL :: tnodes_restart
131 CHARACTER(len=*),
PARAMETER :: routinen =
'simpsonrule_init'
133 INTEGER :: handle, icol, irow, ncols, nrows
134 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :), &
135 POINTER :: w_data, w_data_my
136 TYPE(cp_fm_struct_type),
POINTER :: fm_struct
138 CALL timeset(routinen, handle)
143 nnodes = 4*((nnodes - 1)/4) + 1
145 sr_env%shape_id = shape_id
149 sr_env%error = huge(0.0_dp)
150 sr_env%error_conv = 0.0_dp
152 NULLIFY (sr_env%error_fm, sr_env%weights)
153 CALL cp_fm_get_info(weights, local_data=w_data, nrow_local=nrows, ncol_local=ncols, matrix_struct=fm_struct)
154 ALLOCATE (sr_env%error_fm, sr_env%weights)
162 w_data_my(irow, icol) = abs(w_data(irow, icol))/15.0_dp
166 NULLIFY (sr_env%integral, sr_env%integral_conv)
167 NULLIFY (sr_env%integral_abc, sr_env%integral_cde, sr_env%integral_ace)
169 ALLOCATE (sr_env%tnodes(nnodes))
171 IF (
PRESENT(tnodes_restart))
THEN
172 sr_env%tnodes(1:nnodes) = tnodes_restart(1:nnodes)
174 CALL equidistant_nodes_a_b(-1.0_dp, 1.0_dp, nnodes, sr_env%tnodes)
178 CALL timestop(handle)
188 TYPE(simpsonrule_type),
INTENT(inout) :: sr_env
190 CHARACTER(len=*),
PARAMETER :: routinen =
'simpsonrule_release'
192 INTEGER :: handle, interval
194 CALL timeset(routinen, handle)
195 IF (
ALLOCATED(sr_env%subintervals))
THEN
196 DO interval =
SIZE(sr_env%subintervals), 1, -1
204 DEALLOCATE (sr_env%subintervals)
207 IF (
ASSOCIATED(sr_env%integral))
THEN
209 DEALLOCATE (sr_env%integral)
210 NULLIFY (sr_env%integral)
212 IF (
ASSOCIATED(sr_env%integral_conv))
THEN
214 DEALLOCATE (sr_env%integral_conv)
215 NULLIFY (sr_env%integral_conv)
217 IF (
ASSOCIATED(sr_env%integral_abc))
THEN
219 DEALLOCATE (sr_env%integral_abc)
220 NULLIFY (sr_env%integral_abc)
222 IF (
ASSOCIATED(sr_env%integral_cde))
THEN
224 DEALLOCATE (sr_env%integral_cde)
225 NULLIFY (sr_env%integral_cde)
227 IF (
ASSOCIATED(sr_env%integral_ace))
THEN
229 DEALLOCATE (sr_env%integral_ace)
230 NULLIFY (sr_env%integral_ace)
232 IF (
ASSOCIATED(sr_env%error_fm))
THEN
233 CALL cp_fm_release(sr_env%error_fm)
234 DEALLOCATE (sr_env%error_fm)
235 NULLIFY (sr_env%error_fm)
237 IF (
ASSOCIATED(sr_env%weights))
THEN
238 CALL cp_fm_release(sr_env%weights)
239 DEALLOCATE (sr_env%weights)
240 NULLIFY (sr_env%weights)
243 IF (
ALLOCATED(sr_env%tnodes))
DEALLOCATE (sr_env%tnodes)
245 CALL timestop(handle)
259 TYPE(simpsonrule_type),
INTENT(inout) :: sr_env
260 INTEGER,
INTENT(inout) :: nnodes
261 COMPLEX(kind=dp),
DIMENSION(nnodes),
INTENT(out) :: xnodes_next
263 CHARACTER(len=*),
PARAMETER :: routinen =
'simpsonrule_get_next_nodes'
265 INTEGER :: handle, nnodes_old
266 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: tnodes, tnodes_old
268 CALL timeset(routinen, handle)
269 ALLOCATE (tnodes(nnodes))
271 CALL simpsonrule_get_next_nodes_real(sr_env, tnodes, nnodes)
273 CALL move_alloc(sr_env%tnodes, tnodes_old)
274 nnodes_old =
SIZE(tnodes_old)
276 ALLOCATE (sr_env%tnodes(nnodes_old + nnodes))
277 sr_env%tnodes(1:nnodes_old) = tnodes_old(1:nnodes_old)
278 sr_env%tnodes(nnodes_old + 1:nnodes_old + nnodes) = tnodes(1:nnodes)
279 DEALLOCATE (tnodes_old)
285 CALL timestop(handle)
296 SUBROUTINE simpsonrule_get_next_nodes_real(sr_env, xnodes_unity, nnodes)
297 TYPE(simpsonrule_type),
INTENT(in) :: sr_env
298 REAL(kind=
dp),
DIMENSION(:),
INTENT(out) :: xnodes_unity
299 INTEGER,
INTENT(out) :: nnodes
301 CHARACTER(len=*),
PARAMETER :: routinen =
'simpsonrule_get_next_nodes_real'
303 INTEGER :: handle, interval, nintervals
305 CALL timeset(routinen, handle)
307 IF (
ALLOCATED(sr_env%subintervals))
THEN
308 nintervals =
SIZE(sr_env%subintervals)
313 IF (nintervals > 0)
THEN
314 IF (
SIZE(xnodes_unity) < 4*nintervals) &
315 nintervals =
SIZE(xnodes_unity)/4
317 DO interval = 1, nintervals
318 xnodes_unity(4*interval - 3) = 0.125_dp* &
319 (7.0_dp*sr_env%subintervals(interval)%lb + sr_env%subintervals(interval)%ub)
320 xnodes_unity(4*interval - 2) = 0.125_dp* &
321 (5.0_dp*sr_env%subintervals(interval)%lb + 3.0_dp*sr_env%subintervals(interval)%ub)
322 xnodes_unity(4*interval - 1) = 0.125_dp* &
323 (3.0_dp*sr_env%subintervals(interval)%lb + 5.0_dp*sr_env%subintervals(interval)%ub)
324 xnodes_unity(4*interval) = 0.125_dp*(sr_env%subintervals(interval)%lb + 7.0_dp*sr_env%subintervals(interval)%ub)
328 nnodes = 4*nintervals
329 CALL timestop(handle)
330 END SUBROUTINE simpsonrule_get_next_nodes_real
340 TYPE(simpsonrule_type),
INTENT(inout) :: sr_env
341 TYPE(cp_cfm_type),
DIMENSION(:),
INTENT(inout) :: zdata_next
343 CHARACTER(len=*),
PARAMETER :: routinen =
'simpsonrule_refine_integral'
344 TYPE(cp_cfm_type),
PARAMETER :: cfm_null = cp_cfm_type()
346 COMPLEX(kind=dp),
ALLOCATABLE,
DIMENSION(:) :: zscale
347 COMPLEX(kind=dp),
CONTIGUOUS,
DIMENSION(:, :), &
348 POINTER :: error_zdata
349 INTEGER :: handle, interval, ipoint, jpoint, &
350 nintervals, nintervals_exist, npoints
351 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: inds
352 LOGICAL :: interval_converged, interval_exists
353 REAL(kind=
dp) :: my_bound, rscale
354 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: errors
355 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :), &
356 POINTER :: error_rdata
357 TYPE(cp_fm_struct_type),
POINTER :: fm_struct
358 TYPE(simpsonrule_subinterval_type),
ALLOCATABLE, &
359 DIMENSION(:) :: subintervals
361 CALL timeset(routinen, handle)
363 npoints =
SIZE(zdata_next)
364 IF (
ASSOCIATED(sr_env%integral))
THEN
368 cpassert(npoints > 0 .AND. mod(npoints, 4) == 0)
374 cpassert(npoints > 1 .AND. mod(npoints, 4) == 1)
378 nintervals_exist =
SIZE(sr_env%tnodes)
379 cpassert(nintervals_exist >= npoints)
380 ALLOCATE (zscale(npoints))
383 sr_env%a, sr_env%b, sr_env%shape_id, weights=zscale)
386 DO ipoint = 1, npoints
387 CALL cp_cfm_scale(zscale(ipoint), zdata_next(ipoint))
393 nintervals = npoints/4
394 IF (
ASSOCIATED(sr_env%integral))
THEN
396 nintervals_exist =
SIZE(sr_env%subintervals)
397 cpassert(nintervals <= nintervals_exist)
399 ALLOCATE (subintervals(nintervals_exist + nintervals))
401 DO interval = 1, nintervals
402 subintervals(2*interval - 1)%lb = sr_env%subintervals(interval)%lb
403 subintervals(2*interval - 1)%ub = 0.5_dp*(sr_env%subintervals(interval)%lb + sr_env%subintervals(interval)%ub)
404 subintervals(2*interval - 1)%conv = 0.5_dp*sr_env%subintervals(interval)%conv
405 subintervals(2*interval - 1)%fa = sr_env%subintervals(interval)%fa
406 subintervals(2*interval - 1)%fb = zdata_next(4*interval - 3)
407 subintervals(2*interval - 1)%fc = sr_env%subintervals(interval)%fb
408 subintervals(2*interval - 1)%fd = zdata_next(4*interval - 2)
409 subintervals(2*interval - 1)%fe = sr_env%subintervals(interval)%fc
411 subintervals(2*interval)%lb = subintervals(2*interval - 1)%ub
412 subintervals(2*interval)%ub = sr_env%subintervals(interval)%ub
413 subintervals(2*interval)%conv = subintervals(2*interval - 1)%conv
414 subintervals(2*interval)%fa = sr_env%subintervals(interval)%fc
415 subintervals(2*interval)%fb = zdata_next(4*interval - 1)
416 subintervals(2*interval)%fc = sr_env%subintervals(interval)%fd
417 subintervals(2*interval)%fd = zdata_next(4*interval)
418 subintervals(2*interval)%fe = sr_env%subintervals(interval)%fe
420 zdata_next(4*interval - 3:4*interval) = cfm_null
423 DO interval = nintervals + 1, nintervals_exist
424 subintervals(interval + nintervals) = sr_env%subintervals(interval)
426 DEALLOCATE (sr_env%subintervals)
430 ALLOCATE (sr_env%integral, sr_env%integral_conv, &
431 sr_env%integral_abc, sr_env%integral_cde, sr_env%integral_ace)
440 ALLOCATE (subintervals(nintervals))
442 rscale = 1.0_dp/real(nintervals, kind=
dp)
444 DO interval = 1, nintervals
446 subintervals(interval)%lb = sr_env%tnodes(4*interval - 3)
447 subintervals(interval)%ub = sr_env%tnodes(4*interval + 1)
448 subintervals(interval)%conv = rscale*sr_env%conv
450 subintervals(interval)%fa = zdata_next(4*interval - 3)
451 subintervals(interval)%fb = zdata_next(4*interval - 2)
452 subintervals(interval)%fc = zdata_next(4*interval - 1)
453 subintervals(interval)%fd = zdata_next(4*interval)
454 subintervals(interval)%fe = zdata_next(4*interval + 1)
460 zdata_next(1:npoints) = cfm_null
466 CALL cp_cfm_to_cfm(sr_env%integral_conv, sr_env%integral)
467 sr_env%error = sr_env%error_conv
468 nintervals_exist =
SIZE(subintervals)
470 DO interval = 1, nintervals_exist
471 rscale = subintervals(interval)%ub - subintervals(interval)%lb
472 CALL do_simpson_rule(sr_env%integral_ace, &
473 subintervals(interval)%fa, &
474 subintervals(interval)%fc, &
475 subintervals(interval)%fe, &
477 CALL do_simpson_rule(sr_env%integral_abc, &
478 subintervals(interval)%fa, &
479 subintervals(interval)%fb, &
480 subintervals(interval)%fc, &
482 CALL do_simpson_rule(sr_env%integral_cde, &
483 subintervals(interval)%fc, &
484 subintervals(interval)%fd, &
485 subintervals(interval)%fe, &
492 CALL do_boole_rule(sr_env%integral_abc, &
493 subintervals(interval)%fa, &
494 subintervals(interval)%fb, &
495 subintervals(interval)%fc, &
496 subintervals(interval)%fd, &
497 subintervals(interval)%fe, &
498 0.5_dp*rscale, sr_env%integral_cde)
504 error_rdata(:, :) = abs(error_zdata(:, :))
505 CALL cp_fm_trace(sr_env%error_fm, sr_env%weights, subintervals(interval)%error)
507 sr_env%error = sr_env%error + subintervals(interval)%error
510 IF (subintervals(interval)%error <= subintervals(interval)%conv)
THEN
512 sr_env%error_conv = sr_env%error_conv + subintervals(interval)%error
516 IF (sr_env%error <= sr_env%conv)
THEN
527 DO interval = nintervals_exist, 1, -1
528 interval_exists = .false.
529 my_bound = subintervals(interval)%lb
530 DO jpoint = 1, nintervals_exist
531 IF (subintervals(jpoint)%ub == my_bound)
THEN
532 interval_exists = .true.
536 IF (.NOT. interval_exists)
THEN
539 ELSE IF (interval_converged)
THEN
549 ALLOCATE (errors(nintervals_exist), inds(nintervals_exist))
552 DO interval = 1, nintervals_exist
553 errors(interval) = subintervals(interval)%error
555 IF (subintervals(interval)%error > subintervals(interval)%conv) &
556 nintervals = nintervals + 1
559 CALL sort(errors, nintervals_exist, inds)
561 IF (nintervals > 0) &
562 ALLOCATE (sr_env%subintervals(nintervals))
565 DO ipoint = nintervals_exist, 1, -1
566 interval = inds(ipoint)
568 IF (subintervals(interval)%error > subintervals(interval)%conv)
THEN
569 nintervals = nintervals + 1
571 sr_env%subintervals(nintervals) = subintervals(interval)
575 interval_exists = .false.
576 my_bound = subintervals(interval)%lb
577 DO jpoint = 1, nintervals_exist
578 IF (subintervals(jpoint)%ub == my_bound)
THEN
579 interval_exists = .true.
583 IF (.NOT. interval_exists)
THEN
586 ELSE IF (interval_converged)
THEN
595 interval_exists = .false.
596 interval_converged = .false.
597 my_bound = subintervals(interval)%ub
598 DO jpoint = 1, nintervals_exist
599 IF (subintervals(jpoint)%lb == my_bound)
THEN
600 interval_exists = .true.
601 IF (subintervals(jpoint)%error <= subintervals(jpoint)%conv) interval_converged = .true.
605 IF (.NOT. interval_exists .OR. interval_converged)
THEN
611 DEALLOCATE (errors, inds)
614 DEALLOCATE (subintervals)
616 CALL timestop(handle)
629 SUBROUTINE do_simpson_rule(integral, fa, fb, fc, length)
630 TYPE(cp_cfm_type),
INTENT(IN) :: integral, fa, fb, fc
631 REAL(kind=
dp),
INTENT(in) :: length
633 CALL cp_cfm_to_cfm(fa, integral)
636 CALL cp_cfm_scale(length/6.0_dp, integral)
637 END SUBROUTINE do_simpson_rule
653 SUBROUTINE do_boole_rule(integral, fa, fb, fc, fd, fe, length, work)
654 TYPE(cp_cfm_type),
INTENT(IN) :: integral, fa, fb, fc, fd, fe
655 REAL(kind=
dp),
INTENT(in) :: length
656 TYPE(cp_cfm_type),
INTENT(IN) :: work
658 REAL(kind=
dp) :: rscale
660 rscale = length/90.0_dp
662 CALL cp_cfm_to_cfm(fc, integral)
663 CALL cp_cfm_scale(12.0_dp*rscale, integral)
665 CALL cp_cfm_to_cfm(fa, work)
667 CALL cp_cfm_scale(7.0_dp*rscale, work)
670 CALL cp_cfm_to_cfm(fb, work)
672 CALL cp_cfm_scale(32.0_dp*rscale, work)
674 END SUBROUTINE do_boole_rule
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_create(matrix, matrix_struct, name)
Creates a new full matrix with the given structure.
subroutine, public cp_cfm_release(matrix)
Releases a full matrix.
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.
subroutine, public cp_cfm_set_all(matrix, alpha, beta)
Set all elements of the full matrix to alpha. Besides, set all diagonal matrix elements to beta (if g...
basic linear algebra operations for full matrices
represent the structure of a full matrix
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, use_sp)
creates a new full matrix with the given structure
Defines the basic variable types.
integer, parameter, public dp
Definition of mathematical constants and functions.
real(kind=dp), parameter, public pi
complex(kind=dp), parameter, public z_one
complex(kind=dp), parameter, public z_zero
Adaptive Simpson's rule algorithm to integrate a complex-valued function in a complex plane.
integer, parameter, public sr_shape_arc
subroutine, public simpsonrule_refine_integral(sr_env, zdata_next)
Compute integral using the simpson's rules.
subroutine, public simpsonrule_init(sr_env, xnodes, nnodes, a, b, shape_id, conv, weights, tnodes_restart)
Initialise a Simpson's rule environment variable.
subroutine, public simpsonrule_release(sr_env)
Release a Simpson's rule environment variable.
integer, parameter, public sr_shape_linear
subroutine, public simpsonrule_get_next_nodes(sr_env, xnodes_next, nnodes)
Get the next set of nodes where to compute integrand.
Helper functions for integration routines.
subroutine, public rescale_normalised_nodes(nnodes, tnodes, a, b, shape_id, xnodes, weights)
integer, parameter, public contour_shape_arc
integer, parameter, public contour_shape_linear
All kind of helpful little routines.