!>
!> @file tlocintv.f90
!>
!> @brief
!>
!> @copyright
!> Copyright (©) 2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
!> SPC (Swiss Plasma Center)
!>
!> SPClibs is free software: you can redistribute it and/or modify it under
!> the terms of the GNU Lesser General Public License as published by the Free
!> Software Foundation, either version 3 of the License, or (at your option)
!> any later version.
!>
!> SPClibs is distributed in the hope that it will be useful, but WITHOUT ANY
!> WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
!> FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
!>
!> You should have received a copy of the GNU Lesser General Public License
!> along with this program. If not, see .
!>
!> @author
!> (in alphabetical order)
!> @author Trach-Minh Tran
!>
PROGRAM main
!
! Optimization of locintv
!
USE bsplines
IMPLICIT NONE
INTEGER :: nx, nidbas, ngauss, np, nits
DOUBLE PRECISION :: a, b, coefs(5)
DOUBLE PRECISION, DIMENSION(:), ALLOCATABLE :: xgrid
TYPE(spline1d) :: splx
!
INTEGER :: i, nerrs, it
DOUBLE PRECISION :: t0, t1, seconds, tscal, tscal_new, tvec, tvec_new
DOUBLE PRECISION, ALLOCATABLE :: xp(:)
INTEGER, ALLOCATABLE :: left(:)
!
INTERFACE
SUBROUTINE meshdist(coefs, x, nx)
DOUBLE PRECISION, INTENT(in) :: coefs(5)
INTEGER, INTENT(iN) :: nx
DOUBLE PRECISION, INTENT(inout) :: x(0:nx)
END SUBROUTINE meshdist
END INTERFACE
!
NAMELIST /newrun/ nx, nidbas, ngauss, np, nits, a, b, coefs
!===========================================================================
! Read in data
!
nx = 8 ! Number oh intevals in x
nidbas = 3 ! Degree of splines
ngauss = 4 ! Number of Gauss points/interval
np = 10 ! Number of random points in [a,b]
nits = 1000000
a = 0.0
b = 1.0
coefs(1:5) = (/0.2d0, 1.d0, 0.d0, 0.d0, 1.d0/) ! Mesh point distribution function
! see function FDIST in MESHDIST
!
READ(*,newrun)
WRITE(*,newrun)
!
! Define grid on x axis
!
ALLOCATE(xgrid(0:nx))
xgrid(0) = a
xgrid(nx) = b
CALL meshdist(coefs, xgrid, nx)
WRITE(*,'(/a/(10f8.3))') 'XGRID', xgrid(0:nx)
WRITE(*,'(a/(10f8.3))') 'Diff XGRID', (xgrid(i)-xgrid(i-1), i=1,nx)
!
! Set up spline
!
CALL set_spline(nidbas, ngauss, xgrid, splx)
WRITE(*,'(a,l1)') 'Is mesh equidistant? ', splx%nlequid
!
! Test locintv
!
ALLOCATE(xp(np))
ALLOCATE(left(np))
xp(:) = (b-a)*xp(:) + a
tscal = 0.0d0
tscal_new = 0.0d0
tvec = 0.0d0
tvec_new = 0.0d0
!
nerrs = 0
DO it=1,nits
CALL RANDOM_NUMBER(xp)
t0 = seconds()
DO i=1,np
CALL locintv_old(splx, xp(i), left(i))
END DO
tscal = tscal + seconds()-t0
nerrs = nerrs + COUNT(.NOT.in_interv(xp, left))
!
t0 = seconds()
DO i=1,np
CALL locintv(splx, xp(i), left(i))
END DO
tscal_new = tscal_new + seconds()-t0
nerrs = nerrs + COUNT(.NOT.in_interv(xp, left))
!
t0 = seconds()
CALL locintv_old(splx, xp, left)
tvec = tvec + seconds()-t0
nerrs = nerrs + COUNT(.NOT.in_interv(xp, left))
!
t0 = seconds()
CALL locintv(splx, xp, left)
tvec_new = tvec_new + seconds()-t0
nerrs = nerrs + COUNT(.NOT.in_interv(xp, left))
END DO
PRINT*, 'nerrs =', nerrs
!
tscal = tscal/(REAL(nits*np,8))
tscal_new = tscal_new/(REAL(nits*np,8))
tvec = tvec/(REAL(nits*np,8))
tvec_new = tvec_new/(REAL(nits*np,8))
WRITE(*,'(4a12)') 'scalar', 'scalar new', 'vector', 'vector new'
WRITE(*,'(4(1pe12.3))') tscal, tscal_new, tvec, tvec_new
!
! Clean up
!
DEALLOCATE(xp)
DEALLOCATE(left)
DEALLOCATE(xgrid)
CALL destroy_sp(splx)
!
CONTAINS
LOGICAL ELEMENTAL FUNCTION in_interv(x, l)
DOUBLE PRECISION, INTENT(in) :: x
INTEGER, INTENT(in) :: l
in_interv = x.GE.xgrid(l) .AND. x.LT.xgrid(l+1)
END FUNCTION in_interv
END PROGRAM main