!>
!> @file tmassmat.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
!
! FT of mass matrix
!
USE bsplines
USE matrix
!
IMPLICIT NONE
INTEGER :: nx, nidbas
INTEGER :: ngauss, nrank, kl, ku
INTEGER :: i, k, kmin, kmax
DOUBLE PRECISION :: pi, xlenght, dx, arg0, arg
DOUBLE PRECISION, ALLOCATABLE :: xgrid(:), arow(:)
DOUBLE PRECISION, ALLOCATABLE :: fftmassm1(:), fftmassm2(:), fftmassm3(:)
DOUBLE PRECISION, ALLOCATABLE :: fftmass_shifted(:)
TYPE(spline1d) :: splx
TYPE(periodic_mat) :: massm
!
NAMELIST /newrun/ nx, nidbas, xlenght
!================================================================================
! 1.0 Prologue
!
pi = 4.0d0*ATAN(1.0d0)
!
nx = 8
nidbas = 3
xlenght = 2.0d0*pi
!
READ(*,newrun)
WRITE(*,newrun)
!
ngauss = nidbas+1 ! Exact integration for polynomials of degree 2*nidbas
!
ALLOCATE(xgrid(0:nx))
dx = xlenght/REAL(nx)
xgrid = (/ (i*dx,i=0,nx) /)
WRITE(*,'(a/(10f8.3))') 'xgrid', xgrid
!
CALL set_spline(nidbas, ngauss, xgrid, splx, .TRUE.)
!===========================================================================
! 2.0 Mass matrix
nrank = nx
kl = nidbas
ku = kl
CALL init(kl, ku, nrank, 1, massm)
CALL dismat(splx, massm)
!
ALLOCATE(arow(nrank))
!!$ WRITE(*,'(/a)') 'Mass matrix'
!!$ DO i=1,nrank
!!$ CALL getrow(massm, i, arow)
!!$ WRITE(*,'(10(1pe12.4))') arow
!!$ END DO
!===========================================================================
! 3.0 Fourier transform of Mass matrix
!
ALLOCATE(fftmassm1(0:nx-1))
ALLOCATE(fftmassm2(0:nx-1))
ALLOCATE(fftmassm3(0:nx-1))
IF(nidbas.LE.3) THEN
CALL analytic(nidbas, fftmassm1)
fftmassm1 = dx*fftmassm1
WRITE(*,'(/a/(10(1pe12.4)))') 'Analytic', fftmassm1
END IF
!
CALL calc_fftmass_old(splx, fftmassm2)
WRITE(*,'(/a/(10(1pe12.4)))') 'Old version', fftmassm2
IF(nidbas.LE.3) THEN
WRITE(*,'(a,1pe12.4)') 'error =', MAXVAL(ABS(fftmassm2-fftmassm1))
END IF
!
! Init DFT
kmin = -nx/2
kmax = nx/2-1
CALL init_dft(splx, kmin, kmax)
!
ALLOCATE(fftmass_shifted(kmin:kmax))
CALL calc_fftmass(splx, fftmass_shifted)
DO k=kmin, kmax
fftmassm3(MODULO(k+nx,nx))=fftmass_shifted(k)
END DO
WRITE(*,'(/a/(10(1pe12.4)))') 'New version', fftmassm3
WRITE(*,'(a,1pe12.4)') 'error =', MAXVAL(ABS(fftmassm3-fftmassm2))
!
! Check dftcoefs
WRITE(*,'(/a)') 'Check DFT of splines'
PRINT*, 'dims of dftcoefs', SHAPE(splx%dft%coefs)
DO i=0,nidbas
WRITE(*,'(a,i3,2(1pe12.4))') 'Sum of coefs for spline', i, &
& SUM(splx%dft%coefs(:,i))
END DO
!===========================================================================
! 9.0 Clean up
!
DEALLOCATE(xgrid)
DEALLOCATE(fftmassm1)
DEALLOCATE(fftmassm2)
DEALLOCATE(fftmassm3)
DEALLOCATE(fftmass_shifted)
DEALLOCATE(arow)
CALL destroy(massm)
CALL destroy_sp(splx)
CONTAINS
!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
SUBROUTINE dismat(spl, mat)
TYPE(spline1d) :: spl
TYPE(periodic_mat) :: mat
INTEGER :: dim, nx, nidbas, ngauss
DOUBLE PRECISION, ALLOCATABLE :: fun(:,:), xgauss(:), wgauss(:)
INTEGER :: i, igauss, iw, jt, irow, jcol
DOUBLE PRECISION :: contrib
!
CALL get_dim(spl, dim, nx, nidbas)
ALLOCATE(fun(0:nidbas,1)) ! Spline
CALL get_gauss(spl, ngauss)
ALLOCATE(xgauss(ngauss), wgauss(ngauss))
!
DO i=1,nx
CALL get_gauss(spl, ngauss, i, xgauss, wgauss)
DO igauss=1,ngauss
CALL basfun(xgauss(igauss), spl, fun, i)
DO jt=0,nidbas
DO iw=0,nidbas
contrib = fun(jt,1) * fun(iw,1) * wgauss(igauss)
irow=MODULO(i+iw-1,nx) + 1 ! Periodic BC
jcol=MODULO(i+jt-1,nx) + 1
CALL updtmat(mat, irow, jcol, contrib)
END DO
END DO
END DO
END DO
!
DEALLOCATE(fun)
DEALLOCATE(xgauss, wgauss)
END SUBROUTINE dismat
!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
SUBROUTINE analytic(nidbas, mat)
!
! Analytic form for nidbas .le. 3
!
INTEGER, INTENT(in) :: nidbas
DOUBLE PRECISION, INTENT(out) :: mat(0:)
DOUBLE PRECISION :: arg0, arg, cosk
INTEGER :: n, k
!
n = SIZE(mat)
arg0 = 2.0d0*pi/REAL(n,8)
DO k=0,n-1
arg = k*arg0
cosk = COS(arg)
SELECT CASE (nidbas)
CASE (1)
mat(k) = (2.0d0 + cosk)/3.0d0
CASE (2)
mat(k) = (16.0d0 + cosk*(13.0d0+cosk))/30.0d0
CASE (3)
mat(k) = (272.0d0 + cosk*(297.0d0+cosk*(60.0d0+cosk)))/630.0d0
CASE default
WRITE(*,'(a,i4,a)') 'ANALYTIC: nidbas =', nidbas, ' is not implemented!'
STOP
END SELECT
END DO
END SUBROUTINE analytic
END PROGRAM main