Potential.f90 Source File


Source Code

module Potential
! Version mit Speedup durch Vermeiden doppelter Integrationen
! zusätzlicher Speedup durch Berücksichtigung von verschwindenden rel. Gaunt-Koeffizienten

use mod_datatypes, only: dp

contains

subroutine PotentialMatrixArray(lcut,lcut_input,zatom,meshpoints,nrmax,kinenergy,VLLin,PotMatrixArray)
use SpinSphericals
use Lebedev
use DiracConfig
implicit none

! input 
integer                                     :: lcut, lcut_input, nrmax
complex (kind=dp)                              :: kinenergy
double precision                            :: meshpoints(nrmax)
double precision                            :: zatom,VLLin(nrmax,(2*lcut+1)**2,2)

! output
complex (kind=dp)                              :: PotMatrixArray(:,:,:)

! other variables
integer                                     :: k
complex (kind=dp), allocatable, dimension(:,:)   :: PotMatrix
complex (kind=dp), allocatable                  :: chi1array(:,:), chi2array(:,:)
double precision                            :: theta_array(integrationpoints),phi_array(integrationpoints), weight_array(integrationpoints)
integer, allocatable                         :: DcoeffIndexListA(:,:), DcoeffIndexListB(:,:)
complex (kind=dp), allocatable                  :: DcoeffListA(:), DcoeffListB(:)

if(verbose > 0) then
    write(*,*) ""
    write(*,*) ""
    write(*,*) "  #############################################################"
    write(*,*) "  #                                                           #"
    write(*,*) "  #          FULL POTENTIAL SINGLE-SITE DIRAC SOLVER          #"
    write(*,*) "  #          Pascal Kordt, July 2010 - September 2011         #"
    write(*,*) "  #                                                           #"
    write(*,*) "  #############################################################"
    write(*,*) ""
    write(*,*) "kinenergy=",kinenergy
    write(*,*) "lcut=",lcut
    write(*,*) "zatom=",zatom
    write(*,*) "nrmax=",nrmax
    write(*,*) ""
end if

call makeSpinSphericalArray(lcut,chi1array,chi2array)
call lebedevarray(theta_array,phi_array,weight_array)


! wPot-Version
if(spherical_only /= 1) then
    if(verbose > 0) then
        write(*,*) "******* full potential mode *******"
    end if
    call readDcoeff(lcut,DcoeffIndexListA,DcoeffIndexListB,DcoeffListA,DcoeffListB)
else
    if(verbose > 0) then
        write(*,*) "*** quick mode for spherical potentials without magnetic field B ***"
    end if
end if

write(*,*) ""
write(*,*) "Starting to calculate the w-coefficients for each r-value of the mesh"
do k=1,nrmax
    if(verbose >1 ) then
        write(*,*)
        write(*,*) "MESH POINT ",k," OF ",nrmax
     end if
!    r = meshpoints(k)
    call PotentialSuperMatrix(lcut,lcut_input,zatom,meshpoints,k,kinenergy,chi1array,chi2array,theta_array,phi_array,weight_array,DcoeffIndexListA,DcoeffIndexListB,DcoeffListA,DcoeffListB,VLLin,PotMatrix)
    PotMatrixArray(:,:,k) = PotMatrix(:,:)
end do
write(*,*) "done. (w-coefficients)"

end subroutine PotentialMatrixArray


subroutine PotentialSuperMatrix(lcut,lcut_input,zatom,meshpoints,nr,kinenergy,chi1array,chi2array,theta_array,phi_array,weight_array,DcoeffIndexListA,DcoeffIndexListB,DcoeffListA,DcoeffListB,VLLin,PotMatrix)
use Constants
use SpinSphericals
use Lebedev
use DiracConfig
implicit none

! l cut-off for the expansion in spin spherical harmonics
integer                         :: lcut
double precision                :: zatom,meshpoints(:)
integer                         :: nr

! l cut-off for the input potential, expanded in spherical harmonics
integer                         :: lcut_input
double precision                :: r
complex (kind=dp)                  :: kinenergy
complex (kind=dp), allocatable      :: chi1array(:,:), chi2array(:,:)
double precision                :: VLLin(:,:,:)


complex (kind=dp)                  :: energy
integer                         :: Lambdacut,Lambda1,Lambda2
complex (kind=dp), allocatable, dimension(:,:,:) :: wcoeff
complex (kind=dp), allocatable, dimension(:,:) :: PotMatrix

double precision                 :: theta_array(integrationpoints), phi_array(integrationpoints), weight_array(integrationpoints)
integer, allocatable              :: DcoeffIndexListA(:,:), DcoeffIndexListB(:,:)
complex (kind=dp), allocatable       :: DcoeffListA(:), DcoeffListB(:)

r = meshpoints(nr)

Lambdacut = getLambdacut(lcut)
if(.NOT. allocated(PotMatrix)) then
    allocate(PotMatrix(2*Lambdacut,2*Lambdacut))
end if

energy = kinenergy + emass * lightspeed**2

if(spherical_only == 1) then
    ! accelerated calculation for spherical potentials with B=0
    call wPotentialExpansionNoB(lcut,lcut_input,zatom,meshpoints,nr,chi1array,chi2array,theta_array,phi_array,weight_array,DcoeffIndexListA,DcoeffIndexListB,DcoeffListA,DcoeffListB,VLLin,wcoeff)
else
    ! full-potential calculation
    call wPotentialExpansion(lcut,lcut_input,zatom,meshpoints,nr,chi1array,chi2array,theta_array,phi_array,weight_array,DcoeffIndexListA,DcoeffIndexListB,DcoeffListA,DcoeffListB,VLLin,wcoeff)
end if


! Block a
do Lambda1=1,Lambdacut
do Lambda2=1,Lambdacut
    PotMatrix(Lambda1,Lambda2) = wcoeff(Lambda1,Lambda2,1)
end do
end do

! Block b
do Lambda1=1,Lambdacut
do Lambda2=1,Lambdacut
    PotMatrix(Lambda1,Lambda2+Lambdacut) = wcoeff(Lambda1,Lambda2,2)
end do
end do

! Block c
do Lambda1=1,Lambdacut
do Lambda2=1,Lambdacut
   PotMatrix(Lambda1+Lambdacut,Lambda2) = wcoeff(Lambda1,Lambda2,3)
end do
end do

! Block d
do Lambda1=1,Lambdacut
do Lambda2=1,Lambdacut
    PotMatrix(Lambda1+Lambdacut,Lambda2+Lambdacut) = wcoeff(Lambda1,Lambda2,4)
end do
end do

! write(*,*) "(W+mc²)/c²/hbar²=",(energy + emass * lightspeed**2) / lightspeed**2 / hbar**2
PotMatrix = PotMatrix * (energy + emass * lightspeed**2) / lightspeed**2 / hbar**2

end subroutine PotentialSuperMatrix


subroutine readDcoeff(lcut,DcoeffIndexListA,DcoeffIndexListB,DcoeffListA,DcoeffListB)
use SpinSphericals ! requires SpinSphericals.f90
use Constants ! requires Constants.f90
use Lebedev ! requires Lebedev.f90
use DiracConfig ! requires DiracConfig.f90
use RelativisticGauntCoefficients ! requires RelativisticGauntCoefficients.f90

implicit none

! input
! l cut-off for the expansion in spin spherical harmonics
integer                         :: lcut
integer                         :: Lambdacut
integer, allocatable             :: DcoeffIndexListA(:,:), DcoeffIndexListB(:,:)
complex (kind=dp), allocatable      :: DcoeffListA(:), DcoeffListB(:)
double precision                :: temp_realpart, temp_imagpart
character(len=100)              :: filename
character(len=2)                :: lcutstring
integer                         :: currentline, filelengthA, filelengthB

integer, allocatable, dimension(:):: KappaArray, LambdabarArray
real, allocatable, dimension(:)   :: MuArray

call KappaMuArray(lcut,KappaArray,MuArray)
call makeLambdabarArray(lcut,LambdabarArray)
Lambdacut = LambdabarArray(getLambdacut(lcut))

! read the relativistic Gaunt-coefficients D from the files
write(lcutstring,'(I02.2)') lcut
filename = 'RelativisticGauntCoeffA_lcut'//trim(lcutstring)//'.txt'
if(CheckExistence(filename) /= 1) then
    write(*,*) ""
    write(*,*) "The files containing the relativistic equivalence of the Gaunt coefficients"
    write(*,*) "could not be found in your working directory and will be created now."
    write(*,*) "This can take a while..."
    write(*,*) "Don't worry, this procedure has to be done only once. In future calculations"
    write(*,*) "the file created now will be used."
    write(*,*) ""
    call writeDcoeff(lcut)
end if

if(verbose > 0) then
    write(*,*) "Reading the 1st set of D-coeffients from ", filename
end if
filelengthA = GetNumberOfLines(filename)
open(unit=1,file=filename)

filename = 'RelativisticGauntCoeffB_lcut'//trim(lcutstring)//'.txt'
if(CheckExistence(filename) /= 1) then
    write(*,*) ""
    write(*,*) "The files containing the relativistic equivalence of the Gaunt coefficients"
    write(*,*) "could not be found in your working directory and will be created now."
    write(*,*) "This can take a while..."
    write(*,*) "Don't worry, this procedure has to be done only once. In future calculations"
    write(*,*) "the file created now will be used."
    write(*,*) ""
    call writeDcoeff(lcut)
end if
if(verbose > 0) then
    write(*,*) "Reading the 2nd set of D-coeffients from ", filename
end if
filelengthB = GetNumberOfLines(filename)
open(unit=2,file=filename)

! allocate arrays
allocate(DcoeffIndexListA(4,filelengthA))
allocate(DcoeffIndexListB(4,filelengthB))
allocate(DcoeffListA(filelengthA))
allocate(DcoeffListB(filelengthB))

if(verbose > 0) then
    write(*,*) "Preparing the D-coefficients array..."
end if

do currentline=1,filelengthA
    read(1,'(I3.3, " ",  I3.3, " ", I3.3, " ", I3.3, " ", E23.16, " ", E23.16)') DcoeffIndexListA(1,currentline), DcoeffIndexListA(2,currentline), DcoeffIndexListA(3,currentline), DcoeffIndexListA(4,currentline), temp_realpart, temp_imagpart
    DcoeffListA(currentline) = temp_realpart + i*temp_imagpart
end do

do currentline=1,filelengthB
    read(2,'(I3.3, " ",  I3.3, " ", I3.3, " ", I3.3, " ", E23.16, " ", E23.16)') DcoeffIndexListB(1,currentline), DcoeffIndexListB(2,currentline), DcoeffIndexListB(3,currentline), DcoeffIndexListB(4,currentline), temp_realpart, temp_imagpart
    DcoeffListB(currentline) = temp_realpart + i*temp_imagpart
end do

close(1)
close(2)

if(verbose > 0) then
    write(*,*) "done."
end if
end subroutine readDcoeff


subroutine wPotentialExpansionNoB(lcut,lcut_input,zatom,meshpoints,nr,chi1array,chi2array,theta_array,phi_array,weight_array,DcoeffIndexListA,DcoeffIndexListB,DcoeffListA,DcoeffListB,VLLin,wcoeff)
use Lebedev
use SpinSphericals
use Constants
use DiracConfig

implicit none

! input
! l cut-off for the expansion in spin spherical harmonics
integer                         :: lcut
integer, allocatable             :: DcoeffIndexListA(:,:), DcoeffIndexListB(:,:)
complex (kind=dp), allocatable      :: DcoeffListA(:), DcoeffListB(:)
double precision                :: zatom,VLLin(:,:,:)
double precision                :: meshpoints(:)
integer                         :: nr


! l cut-off for the input potential, expanded in spherical harmonics
integer                         :: lcut_input
double precision                :: r
complex (kind=dp), allocatable      :: chi1array(:,:), chi2array(:,:)
double precision                :: theta_array(integrationpoints), phi_array(integrationpoints), weight_array(integrationpoints)

double precision                :: potPhi
integer                         :: Lambda1, Lambdacut
complex (kind=dp), allocatable      :: wcoeff(:,:,:)
integer, allocatable, dimension(:):: KappaArray, LambdabarArray
real, allocatable, dimension(:)   :: MuArray

r = meshpoints(nr)

Lambdacut = getLambdacut(lcut)
call KappaMuArray(lcut,KappaArray,MuArray)
call makeLambdabarArray(lcut,LambdabarArray)

call getPotPhi(zatom,meshpoints,nr,0.0d0,0.0d0,VLLin,potPhi)

allocate(wcoeff(Lambdacut,Lambdacut,4))
wcoeff(:,:,:) = 0.0d0

if(verbose==2) then
    write(*,*) "computing the w-coefficients"
end if

do Lambda1=1,Lambdacut
    ! only diagonal entries are /= 0
    wcoeff(Lambda1,Lambda1,1) = echarge * potPhi 
    wcoeff(Lambda1,Lambda1,4) = echarge * potPhi 
end do
end subroutine wPotentialExpansionNoB


subroutine wPotentialExpansion(lcut,lcut_input,zatom,meshpoints,nr,chi1array,chi2array,theta_array,phi_array,weight_array,DcoeffIndexListA,DcoeffIndexListB,DcoeffListA,DcoeffListB,VLLin,wcoeff)
use SpinSphericals ! requires SpinSphericals.f90
use Constants ! requires Constants.f90
use Lebedev ! requires Lebedev.f90
use DiracConfig ! requires DiracConfig.f90

implicit none

! input
! l cut-off for the expansion in spin spherical harmonics
integer                         :: lcut
integer, allocatable             :: DcoeffIndexListA(:,:), DcoeffIndexListB(:,:)
complex (kind=dp), allocatable      :: DcoeffListA(:), DcoeffListB(:)

double precision                :: VLLin(:,:,:)
double precision                :: zatom,meshpoints(:)
integer                         :: nr


! l cut-off for the input potential, expanded in spherical harmonics
integer                         :: lcut_input
double precision                :: r
complex (kind=dp), allocatable      :: chi1array(:,:), chi2array(:,:)
double precision                :: theta_array(integrationpoints), phi_array(integrationpoints), weight_array(integrationpoints)

integer                         :: Lambdacut, Lambda1, Lambda2, Lambda3, Lambda4, test_zero, test_nonzero
integer                         :: linecount, filelengthA, filelengthB
complex (kind=dp), allocatable      :: vcoeff(:,:,:), wcoeff(:,:,:)


integer, allocatable, dimension(:):: KappaArray, LambdabarArray
real, allocatable, dimension(:)   :: MuArray

r = meshpoints(nr)

Lambdacut = getLambdacut(lcut)
call KappaMuArray(lcut,KappaArray,MuArray)
call makeLambdabarArray(lcut,LambdabarArray)

allocate(wcoeff(Lambdacut,Lambdacut,4))
wcoeff(:,:,:) = 0.0d0

call PotentialExpansion(lcut,lcut_input,zatom,meshpoints,nr,chi1array,chi2array,theta_array,phi_array,weight_array,VLLin,vcoeff)
if(verbose==2) then
    write(*,*) "computing sums for the the w-coefficients..."
end if

filelengthA = size(DcoeffListA(:))
filelengthB = size(DcoeffListB(:))

do linecount = 1, filelengthA
    Lambda1 = DcoeffIndexListA(1,linecount)
    Lambda2 = DcoeffIndexListA(2,linecount)
    Lambda3 = DcoeffIndexListA(3,linecount)
    Lambda4 = DcoeffIndexListA(4,linecount)
    wcoeff(Lambda1,Lambda4,1) = wcoeff(Lambda1,Lambda4,1) + DcoeffListA(linecount) * vcoeff(Lambda2,Lambda3,1)
end do

do linecount = 1, filelengthB
    Lambda1 = DcoeffIndexListB(1,linecount)
    Lambda2 = DcoeffIndexListB(2,linecount)
    Lambda3 = DcoeffIndexListB(3,linecount)
    Lambda4 = DcoeffIndexListB(4,linecount)
    wcoeff(Lambda1,Lambda4,4) = wcoeff(Lambda1,Lambda4,4) + DcoeffListB(linecount) * vcoeff(Lambda2,Lambda3,4)
end do

! clean up
test_zero=0
test_nonzero=0
do Lambda1=1,Lambdacut
do Lambda4=1,Lambdacut
    test_nonzero=test_nonzero+2
    if(w_eps > 0 .and. abs(wcoeff(Lambda1,Lambda4,1)) < w_eps) then
        wcoeff(Lambda1,Lambda4,1)=0.0d0
        test_zero=test_zero+1
        test_nonzero=test_nonzero-1
    end if
    if(w_eps > 0 .and. abs(wcoeff(Lambda1,Lambda4,4)) < w_eps) then
        wcoeff(Lambda1,Lambda4,4)=0.0d0
        test_zero=test_zero+1
        test_nonzero=test_nonzero-1
    end if
end do
end do

if(verbose==2) then
    write(*,*) "done."
end if

end subroutine wPotentialExpansion


subroutine PotentialExpansion(lcut,lcut_input,zatom,meshpoints,nr,chi1array,chi2array,theta_array,phi_array,weight_array,VLLin,vcoeff)
use SpinSphericals ! requires SpinSphericals.f90
use Constants ! requires Constants.f90
use Lebedev ! requires Lebedev.f90
use DiracConfig ! requires DiracConfig.f90

implicit none

! input
! l cut-off for the expansion in spin spherical harmonics
integer                         :: lcut
double precision                :: VLLin(:,:,:)
double precision                :: zatom,meshpoints(:)
integer                         :: nr

! l cut-off for the input potential, expanded in spherical harmonics
integer                         :: lcut_input
double precision                :: r
complex (kind=dp), allocatable      :: chi1array(:,:), chi2array(:,:)
double precision                :: theta_array(integrationpoints), phi_array(integrationpoints), weight_array(integrationpoints)

! variables
double precision                :: theta,phi


! variables
integer                         :: j,k
double precision                :: deviation
double precision                :: potPhi,potBx,potBy,potBz
double precision                :: eval_phi,eval_theta
integer                         :: out_potprecision
complex (kind=dp), dimension(4,4)  :: potMatrixIn,potMatrix,differenceMatrix ! 4x4 potential matrix

integer                         :: Lambdacut, Lambda1, Lambda2
complex (kind=dp), dimension(4)    :: v
complex (kind=dp), allocatable, dimension(:,:,:) :: vcoeff

integer, allocatable, dimension(:):: KappaArray, LambdabarArray
real, allocatable, dimension(:)   :: MuArray
complex (kind=dp)                  :: chi11,chi12,chi21,chi22
complex (kind=dp), allocatable        :: nuL(:,:,:), nuR(:,:,:)


! test options
! 1: write the precision of the potential expansion for a sample point, 0: don't write it
out_potprecision = 1
! sample point to evaluate
eval_phi   = 0.3d0*Pi
eval_theta = 0.1d0*Pi

r = meshpoints(nr)

Lambdacut = getLambdacut(lcut)
call KappaMuArray(lcut,KappaArray,MuArray)
call makeLambdabarArray(lcut,LambdabarArray)
allocate(vcoeff(Lambdacut,Lambdacut,4))

if(verbose > 1) then
    write(*,*) "computing potential expansion..."
end if

call getPotPhi(zatom,meshpoints,nr,eval_theta,eval_phi,VLLin,potPhi)
call getPotB(zatom,meshpoints,nr,eval_theta,phi,VLLin,potBx,potBy,potBz)
! potPhi now contains the value for the scalar potential Phi and potBx,potBy,potBz the B-Field values


! calculate the potential matrix (this has to be changed in case of a full vector poential A)
potMatrixIn(1,1) = echarge * potPhi - muB * potBz
potMatrixIn(1,2) = - muB * potBx  + i * muB * potBy
potMatrixIn(2,1) = - muB * potBx - i * muB * potBy
potMatrixIn(2,2) = echarge * potPhi + muB * potBz

potMatrixIn(1,3) = 0.0d0
potMatrixIn(1,4) = 0.0d0
potMatrixIn(2,3) = 0.0d0
potMatrixIn(2,4) = 0.0d0

potMatrixIn(3,1) = 0.0d0
potMatrixIn(3,2) = 0.0d0
potMatrixIn(4,1) = 0.0d0
potMatrixIn(4,2) = 0.0d0

potMatrixIn(3,3) = echarge * potPhi + muB * potBz
potMatrixIn(3,4) = muB * potBx - i * muB * potBy
potMatrixIn(4,3) = muB * potBx + i * muB * potBy
potMatrixIn(4,4) = echarge * potPhi - muB * potBz

call nuCoefficients(lcut,zatom,meshpoints,nr,chi1array,chi2array,theta_array,phi_array,weight_array,VLLin,nuL,nuR)

do Lambda1=1,Lambdacut
do Lambda2=1,Lambdacut
  call ExpansionCoefficients(Lambda1,Lambda2,lcut,meshpoints,nr,chi1array,chi2array,theta_array,phi_array,weight_array,nuL,nuR,v)

  do j=1,4
    ! clean up
    if(v_eps > 0 .and. abs(v(j)) < v_eps) then
        v(j)=0.0d0
    end if
  vcoeff(Lambda1,Lambda2,j) = v(j)
  end do
end do
end do


if(verbose>1) then
! calculate the potential matrix and check accuracy
  potMatrix(:,:) = 0
  do Lambda1=1,Lambdacut
  do Lambda2=1,Lambdacut

    call SpinSphericalHarmonic(KappaArray(Lambda1),MuArray(Lambda1),theta,phi,chi11,chi12)
    call SpinSphericalHarmonic(KappaArray(Lambda2),MuArray(Lambda2),theta,phi,chi21,chi22)
    potMatrix(1,1) = potMatrix(1,1) + vcoeff(Lambda1,Lambda2,1) * chi11 * conjg(chi21)
    potMatrix(1,2) = potMatrix(1,2) + vcoeff(Lambda1,Lambda2,1) * chi11 * conjg(chi22)
    potMatrix(2,1) = potMatrix(2,1) + vcoeff(Lambda1,Lambda2,1) * chi12 * conjg(chi21)
    potMatrix(2,2) = potMatrix(2,2) + vcoeff(Lambda1,Lambda2,1) * chi12 * conjg(chi22)

    call SpinSphericalHarmonic(KappaArray(Lambda1),MuArray(Lambda1),theta,phi,chi11,chi12)
    call SpinSphericalHarmonic(KappaArray(LambdabarArray(Lambda2)),MuArray(LambdabarArray(Lambda2)),theta,phi,chi21,chi22)
    potMatrix(1,3) = potMatrix(1,3) + vcoeff(Lambda1,Lambda2,2) * chi11 * conjg(chi21)
    potMatrix(1,4) = potMatrix(1,4) + vcoeff(Lambda1,Lambda2,2) * chi11 * conjg(chi22)
    potMatrix(2,3) = potMatrix(2,3) + vcoeff(Lambda1,Lambda2,2) * chi12 * conjg(chi21)
    potMatrix(2,4) = potMatrix(2,4) + vcoeff(Lambda1,Lambda2,2) * chi12 * conjg(chi22)

    call SpinSphericalHarmonic(KappaArray(LambdabarArray(Lambda1)),MuArray(LambdabarArray(Lambda1)),theta,phi,chi11,chi12)
    call SpinSphericalHarmonic(KappaArray(Lambda2),MuArray(Lambda2),theta,phi,chi21,chi22)
    potMatrix(3,1) = potMatrix(3,1) + vcoeff(Lambda1,Lambda2,3) * chi11 * conjg(chi21)
    potMatrix(3,2) = potMatrix(3,2) + vcoeff(Lambda1,Lambda2,3) * chi11 * conjg(chi22)
    potMatrix(4,1) = potMatrix(4,1) + vcoeff(Lambda1,Lambda2,3) * chi12 * conjg(chi21)
    potMatrix(4,2) = potMatrix(4,2) + vcoeff(Lambda1,Lambda2,3) * chi12 * conjg(chi22)

    call SpinSphericalHarmonic(KappaArray(LambdabarArray(Lambda1)),MuArray(LambdabarArray(Lambda1)),theta,phi,chi11,chi12)
    call SpinSphericalHarmonic(KappaArray(LambdabarArray(Lambda2)),MuArray(LambdabarArray(Lambda2)),theta,phi,chi21,chi22)
    potMatrix(3,3) = potMatrix(3,3) + vcoeff(Lambda1,Lambda2,4) * chi11 * conjg(chi21)
    potMatrix(3,4) = potMatrix(3,4) + vcoeff(Lambda1,Lambda2,4) * chi11 * conjg(chi22)
    potMatrix(4,3) = potMatrix(4,3) + vcoeff(Lambda1,Lambda2,4) * chi12 * conjg(chi21)
    potMatrix(4,4) = potMatrix(4,4) + vcoeff(Lambda1,Lambda2,4) * chi12 * conjg(chi22)
  ! write(*,*) "Lambda1=",Lambda1,"Lambda2=",Lambda2,"v4-coefficient",vcoeff(4,Lambda1,Lambda2)

  end do
  end do

  ! calculate the sum of all absolute values of the difference matrix (matrix 1-norm)
  deviation = 0
  differenceMatrix = potMatrixIn-potMatrix
  do j=1,4
  do k=1,4
    deviation = deviation + abs(differenceMatrix(j,k))
  end do
  end do
  write(*,*) "done. (expansion accuracy: ", deviation, ")"
end if

end subroutine PotentialExpansion


subroutine PotentialExpansionNoB(lcut,lcut_input,zatom,meshpoints,nr,chi1array,chi2array,theta_array,phi_array,weight_array,VLLin,vcoeff)
! obsolete
use SpinSphericals ! requires SpinSphericals.f90
use Constants ! requires Constants.f90
use Lebedev ! requires Lebedev.f90

implicit none

! input
! l cut-off for the expansion in spin spherical harmonics
integer                         :: lcut
double precision                :: zatom,meshpoints(:)
integer                         :: nr

! l cut-off for the input potential, expanded in spherical harmonics
integer                         :: lcut_input
double precision                :: r
complex (kind=dp), allocatable      :: chi1array(:,:), chi2array(:,:)
double precision                :: theta_array(integrationpoints), phi_array(integrationpoints), weight_array(integrationpoints)
double precision                :: VLLin(:,:,:)

! variables
double precision                :: theta,phi

! variables
integer                         :: j,k
double precision                :: deviation
double precision                :: potPhi
double precision                :: eval_phi,eval_theta
complex (kind=dp), dimension(4,4)  :: potMatrixIn,potMatrix,differenceMatrix ! 4x4 potential matrix

integer                         :: Lambdacut, Lambda1, Lambda2
complex (kind=dp), allocatable, dimension(:,:,:) :: vcoeff

integer, allocatable, dimension(:):: KappaArray, LambdabarArray
real, allocatable, dimension(:)   :: MuArray
complex (kind=dp)                  :: chi11,chi12,chi21,chi22

r = meshpoints(nr)

Lambdacut = getLambdacut(lcut)
call KappaMuArray(lcut,KappaArray,MuArray)
call makeLambdabarArray(lcut,LambdabarArray)
allocate(vcoeff(Lambdacut,Lambdacut,4))

vcoeff(:,:,:) = 0.0d0

write(*,*) "Starting to calculate the potential expansion for r=",r
write(*,*) "!!! Using the PotentialExpansionNoB subroutine. This subroutine is obsolete and should only be used for testing! !!!"

! sample point to evaluate
eval_phi   = 0.3d0*Pi
eval_theta = 0.1d0*Pi

call getPotPhi(zatom,meshpoints,nr,eval_theta,eval_phi,VLLin,potPhi)

! calculate the potential matrix (this has to be changed in case of a full vector poential A)
potMatrixIn(1,1) = echarge * PotPhi
potMatrixIn(1,2) = 0.0d0
potMatrixIn(2,1) = 0.0d0
potMatrixIn(2,2) = echarge * PotPhi

potMatrixIn(1,3) = 0.0d0
potMatrixIn(1,4) = 0.0d0
potMatrixIn(2,3) = 0.0d0
potMatrixIn(2,4) = 0.0d0

potMatrixIn(3,1) = 0.0d0
potMatrixIn(3,2) = 0.0d0
potMatrixIn(4,1) = 0.0d0
potMatrixIn(4,2) = 0.0d0

potMatrixIn(3,3) = echarge * PotPhi
potMatrixIn(3,4) = 0.0d0
potMatrixIn(4,3) = 0.0d0
potMatrixIn(4,4) = echarge * PotPhi

! The only entries /= 0 are for Lambda1=Lambda2=1,2 and j=1,4(a block and d block)
! Lambda1=Lambda2=1
vcoeff(1,1,1) = 4*Pi*echarge*PotPhi 
vcoeff(1,1,4) = 4*Pi*echarge*PotPhi 
! Lambda1=Lambda2=2
vcoeff(2,2,1) = 4*Pi*echarge*PotPhi 
vcoeff(2,2,4) = 4*Pi*echarge*PotPhi 

! calculate the potential matrix
potMatrix(:,:) = 0
do Lambda1=1,Lambdacut
do Lambda2=1,Lambdacut

  call SpinSphericalHarmonic(KappaArray(Lambda1),MuArray(Lambda1),theta,phi,chi11,chi12)
  call SpinSphericalHarmonic(KappaArray(Lambda2),MuArray(Lambda2),theta,phi,chi21,chi22)
  potMatrix(1,1) = potMatrix(1,1) + vcoeff(Lambda1,Lambda2,1) * chi11 * conjg(chi21)
  potMatrix(1,2) = potMatrix(1,2) + vcoeff(Lambda1,Lambda2,1) * chi11 * conjg(chi22)
  potMatrix(2,1) = potMatrix(2,1) + vcoeff(Lambda1,Lambda2,1) * chi12 * conjg(chi21)
  potMatrix(2,2) = potMatrix(2,2) + vcoeff(Lambda1,Lambda2,1) * chi12 * conjg(chi22)

  call SpinSphericalHarmonic(KappaArray(Lambda1),MuArray(Lambda1),theta,phi,chi11,chi12)
  call SpinSphericalHarmonic(KappaArray(LambdabarArray(Lambda2)),MuArray(LambdabarArray(Lambda2)),theta,phi,chi21,chi22)
  potMatrix(1,3) = potMatrix(1,3) + vcoeff(Lambda1,Lambda2,2) * chi11 * conjg(chi21)
  potMatrix(1,4) = potMatrix(1,4) + vcoeff(Lambda1,Lambda2,2) * chi11 * conjg(chi22)
  potMatrix(2,3) = potMatrix(2,3) + vcoeff(Lambda1,Lambda2,2) * chi12 * conjg(chi21)
  potMatrix(2,4) = potMatrix(2,4) + vcoeff(Lambda1,Lambda2,2) * chi12 * conjg(chi22)

  call SpinSphericalHarmonic(KappaArray(LambdabarArray(Lambda1)),MuArray(LambdabarArray(Lambda1)),theta,phi,chi11,chi12)
  call SpinSphericalHarmonic(KappaArray(Lambda2),MuArray(Lambda2),theta,phi,chi21,chi22)
  potMatrix(3,1) = potMatrix(3,1) + vcoeff(Lambda1,Lambda2,3) * chi11 * conjg(chi21)
  potMatrix(3,2) = potMatrix(3,2) + vcoeff(Lambda1,Lambda2,3) * chi11 * conjg(chi22)
  potMatrix(4,1) = potMatrix(4,1) + vcoeff(Lambda1,Lambda2,3) * chi12 * conjg(chi21)
  potMatrix(4,2) = potMatrix(4,2) + vcoeff(Lambda1,Lambda2,3) * chi12 * conjg(chi22)

  call SpinSphericalHarmonic(KappaArray(LambdabarArray(Lambda1)),MuArray(LambdabarArray(Lambda1)),theta,phi,chi11,chi12)
  call SpinSphericalHarmonic(KappaArray(LambdabarArray(Lambda2)),MuArray(LambdabarArray(Lambda2)),theta,phi,chi21,chi22)
  potMatrix(3,3) = potMatrix(3,3) + vcoeff(Lambda1,Lambda2,4) * chi11 * conjg(chi21)
  potMatrix(3,4) = potMatrix(3,4) + vcoeff(Lambda1,Lambda2,4) * chi11 * conjg(chi22)
  potMatrix(4,3) = potMatrix(4,3) + vcoeff(Lambda1,Lambda2,4) * chi12 * conjg(chi21)
  potMatrix(4,4) = potMatrix(4,4) + vcoeff(Lambda1,Lambda2,4) * chi12 * conjg(chi22)

end do
end do

! calculate the sum of all absolute values of the difference matrix (matrix 1-norm)
deviation = 0
differenceMatrix = potMatrixIn-potMatrix
do j=1,4
do k=1,4
  deviation = deviation + abs(differenceMatrix(j,k))
end do
end do
write(*,*) "accuracy of the potential expansion (sum of the absolute deviations):", deviation
write(*,*) "...finished calculating the potential expansion for r=",r

end subroutine PotentialExpansionNoB


subroutine makeSpinSphericalArray(lcut,chi1array,chi2array)
  use SpinSphericals
  use Lebedev
  implicit none
  ! input: lcut
  integer                               :: lcut
  ! output: chi1array, chi2array
  complex (kind=dp), allocatable            :: chi1array(:,:), chi2array(:,:)
  
  complex (kind=dp)                        :: chi1,chi2
  double precision                      :: x,y,z,r,theta,phi,weight
  integer                               :: kappa
  real                                  :: mu
  
  integer                               :: Lambdacut, j, Lambda
  integer, allocatable, dimension(:)      :: KappaArray
  real, allocatable, dimension(:)         :: MuArray
  
  Lambdacut = getLambdacut(lcut+1)
  call KappaMuArray(lcut,KappaArray,MuArray)
  
  allocate(chi1array(integrationpoints,Lambdacut))
  allocate(chi2array(integrationpoints,Lambdacut))

  do j=1,integrationpoints
      call lebedevpoint(j,x,y,z,weight)
      call Cartesian2Spherical(x,y,z,r,theta,phi)

      do Lambda=1,Lambdacut
          kappa = KappaArray(Lambda)
          mu    = MuArray(Lambda)
          call SpinSphericalHarmonic(kappa,mu,theta,phi,chi1,chi2)
          chi1array(j,Lambda) = chi1
          chi2array(j,Lambda) = chi2
      end do
  end do
end subroutine makeSpinSphericalArray


subroutine nuCoefficients(lcut,zatom,meshpoints,nr,chi1array,chi2array,theta_array,phi_array,weight_array,VLLin,nuL,nuR)
! input: lcut,position r,SphiSpherical-Arrays chi1array,chi2array
! output nuL(Lambda,matrixindex,eigenvalueindex)
!        nuR(Lambda,matrixindex,eigenvalueindex)
  use SpinSphericals
  use Lebedev
  use DiracConfig
  implicit none
  integer                :: Lambda
  double precision                      :: zatom,meshpoints(:)
  integer                               :: nr

  double precision            :: r_fix
  double precision                      :: theta_array(integrationpoints), phi_array(integrationpoints), weight_array(integrationpoints)
  double precision                      :: VLLin(:,:,:)


  complex (kind=dp), allocatable        :: nuL(:,:,:), nuR(:,:,:)
  integer                :: j
  ! ^ index 1..4 corresponds to a,b,c,d i.e. the different sub-matrices, index i=1,2 corresponds to the different eigenvalues of the respective sub-matrix 
  complex (kind=dp), dimension(4,2)    :: eigenvalue
  complex (kind=dp), dimension(4,2,2)    :: eigenvector
  complex (kind=dp)            :: chi1,chi2
  double precision            :: potPhi,potBx,potBy,potBz
  integer                :: matrixindex,eigenvalueindex
 
  integer                :: lcut, Lambdacut
  integer, allocatable, dimension(:)    :: KappaArray, LambdabarArray
  real, allocatable, dimension(:)        :: MuArray
  complex (kind=dp), allocatable            :: chi1array(:,:), chi2array(:,:)

  r_fix = meshpoints(nr)

  Lambdacut = getLambdacut(lcut)
  call makeLambdabarArray(lcut,LambdabarArray)
  call KappaMuArray(lcut,KappaArray,MuArray)

  allocate(nuL(Lambdacut,4,2))
  allocate(nuR(Lambdacut,4,2))

  nuL(:,:,:)  = 0
  nuR(:,:,:)  = 0

  do j=1,integrationpoints

     call getPotPhi(zatom,meshpoints,nr,theta_array(j),phi_array(j),VLLin,potPhi)
     call getPotB(zatom,meshpoints,nr,theta_array(j),phi_array(j),VLLin,potBx,potBy,potBz) 

    ! get eigenvalue entries of the 2x2 sub-matrices of the 4x4 potential matrix
    call SubMatrixEigenvalue(potPhi,potBx,potBy,potBz,eigenvalue)
    ! get eigenvector entries of the 2x2 sub-matrices of the 4x4 potential matrix
    call SubMatrixEigenvector(potPhi,potBx,potBy,potBz,eigenvector)

    do Lambda=1,Lambdacut
        ! write entries of the Spin Spherical Harmonics into chi1 (1st component) and chi2 (2nd component)
        do matrixindex=1,4
        if(matrixindex==1 .OR. matrixindex==2) then
            chi1 = chi1array(j,Lambda)
            chi2 = chi2array(j,Lambda)
        else if (matrixindex==3 .OR. matrixindex==4) then
            chi1 = chi1array(j,LambdabarArray(Lambda))
            chi2 = chi2array(j,LambdabarArray(Lambda))
        end if
        if(spherical_only/=1 .or. (matrixindex == 1 .or. matrixindex==4)) then
            do eigenvalueindex=1,2
            nuL(Lambda,matrixindex,eigenvalueindex) = nuL(Lambda,matrixindex,eigenvalueindex) + &
                eigenvalue(matrixindex,eigenvalueindex) * (conjg(chi1) * eigenvector(matrixindex,eigenvalueindex,1) + conjg(chi2) * eigenvector(matrixindex,eigenvalueindex,2)) &
                * weight_array(j)
            end do
        end if
        end do ! matrixindex loop

        do matrixindex=1,4
        if(matrixindex==1 .OR. matrixindex==3) then
            chi1 = chi1array(j,Lambda)
            chi2 = chi2array(j,Lambda)
        else if (matrixindex==2 .OR. matrixindex==4) then
            chi1 = chi1array(j,LambdabarArray(Lambda))
            chi2 = chi2array(j,LambdabarArray(Lambda))
        end if
        if(spherical_only/=1 .or. (matrixindex == 1 .or. matrixindex==4)) then
            do eigenvalueindex=1,2
            nuR(Lambda,matrixindex,eigenvalueindex) = nuR(Lambda,matrixindex,eigenvalueindex) + &
                (conjg(eigenvector(matrixindex,eigenvalueindex,1)) * chi1 + conjg(eigenvector(matrixindex,eigenvalueindex,2)) * chi2 ) &
                * weight_array(j)
            end do
        end if
        end do ! matrixindex loop
    end do ! Lambda


  end do ! integrationpoints loop 

end subroutine nuCoefficients



subroutine ExpansionCoefficients(Lambda1,Lambda2,lcut,meshpoints,nr,chi1array,chi2array,theta_array,phi_array,weight_array,nuL,nuR,vcoeff)
! input: Lambda1,Lambda2,lcut,position r,SphiSpherical-Arrays chi1array,chi2array
! output v(1),v(2),v(3),v(4) expansion coefficients
  use SpinSphericals
  use Lebedev
  use DiracConfig
  implicit none
  complex (kind=dp), dimension(4)        :: vcoeff ! index 1..4 corresponds to a,b,c,d
  integer                :: Lambda1, Lambda2
  double precision                      :: meshpoints(:)
  integer                               :: nr

  double precision            :: r_fix
  double precision                      :: theta_array(integrationpoints), phi_array(integrationpoints), weight_array(integrationpoints)

  complex (kind=dp), allocatable        :: nuL(:,:,:), nuR(:,:,:)

  ! ^ index 1..4 corresponds to a,b,c,d i.e. the different sub-matrices, index i=1,2 corresponds to the different eigenvalues of the respective sub-matrix 
  integer                :: matrixindex
 
  integer                :: lcut, Lambdacut, printtimer
  integer, allocatable, dimension(:)    :: KappaArray, LambdabarArray
  real, allocatable, dimension(:)        :: MuArray
  complex (kind=dp), allocatable            :: chi1array(:,:), chi2array(:,:)
  printtimer = 1 ! 1=print computing step times 0=don't
  Lambdacut = getLambdacut(lcut)
  call makeLambdabarArray(lcut,LambdabarArray)
  call KappaMuArray(lcut,KappaArray,MuArray)

  r_fix = meshpoints(nr)

  vcoeff(:) = 0

  do matrixindex=1,4
      vcoeff(matrixindex) = nuL(Lambda1,matrixindex,1) * nuR(Lambda2,matrixindex,1) + nuL(Lambda1,matrixindex,2) * nuR(Lambda2,matrixindex,2)
  end do
end subroutine ExpansionCoefficients



subroutine SubMatrixEigenvalue(potPhi,potBx,potBy,potBz,eigenvalue)
  ! Input:
  ! eigenvalueindex = 1,2 corresponds to the two different eigenvalues of the corresponding sub-matrix
  ! matrixindex = 1,2,3,4 corresponds to a,b,c,d numbering the four different sub-matrices
  ! potPhi: scalar potential
  ! potBx,potBy,potBz: entries of the B-Field
  ! Output
  ! eigenvalue(matrixindex,eigenvalueindex)
  ! matrixindex = 1,2,3,4 corresponds to a,b,c,d numbering the four different sub-matrices
  ! eigenvalueindex = 1,2 corresponds to the two different eigenvalues of the corresponding sub-matrix
  use Constants
  implicit none
  double precision            :: potPhi,potBx,potBy,potBz
  complex (kind=dp), dimension(4,2)    :: eigenvalue
  eigenvalue(1,1) = echarge * potPhi + muB * sqrt(potBx**2 + potBy**2 + potBz**2)
  eigenvalue(1,2) = echarge * potPhi - muB * sqrt(potBx**2 + potBy**2 + potBz**2)
  eigenvalue(2,1) = 0
  eigenvalue(2,2) = 0
  eigenvalue(3,1) = 0
  eigenvalue(3,2) = 0
  eigenvalue(4,1) = echarge * potPhi + muB * sqrt(potBx**2 + potBy**2 + potBz**2)
  eigenvalue(4,2) = echarge * potPhi - muB * sqrt(potBx**2 + potBy**2 + potBz**2)
end subroutine SubMatrixEigenvalue


subroutine SubMatrixEigenvector(potPhi,potBx,potBy,potBz,eigenvector)
  ! Input:
  ! potPhi: scalar potential
  ! potBx,potBy,potBz: entries of the B-Field
  ! Output
  ! eigenvector(matrixindex,eigenvalueindex,entryindex)
  ! eigenvalueindex = 1,2 corresponds to the two different eigenvalues of the corresponding sub-matrix
  ! matrixindex = 1,2,3,4 corresponds to a,b,c,d numbering the four different sub-matrices
  ! ventryindex = 1,2 corresponds to the 1st and 2nd entry of the eigenvector
  use Constants
  implicit none
  double precision            :: potPhi,potBx,potBy,potBz
  complex (kind=dp), dimension(4,2,2)    :: eigenvector
  double precision                      :: norm
  integer                               :: matrixindex, eigenvalueindex
  if(potBx==0 .AND. potBy==0) then

    eigenvector(1,1,1) = 0
    eigenvector(1,1,2) = 1

    eigenvector(1,2,1) = 1
    eigenvector(1,2,2) = 0

    eigenvector(2,1,1) = 0
    eigenvector(2,1,2) = 1

    eigenvector(2,2,1) = 1
    eigenvector(2,2,2) = 0

    eigenvector(3,1,1) = 0
    eigenvector(3,1,2) = 1

    eigenvector(3,2,1) = 1
    eigenvector(3,2,2) = 0

    eigenvector(4,1,1) = 1
    eigenvector(4,1,2) = 0

    eigenvector(4,2,1) = 0
    eigenvector(4,2,2) = 1

else

    if(sqrt(potBx**2 + potBy**2 + potBz**2) + potBz == 0) then
      eigenvector(1,1,1) = 0
    else 
      eigenvector(1,1,1) = (-potBx + i * potBy) / ( sqrt(potBx**2 + potBy**2 + potBz**2) + potBz)
    end if
    eigenvector(1,1,2) = 1

    if(- sqrt(potBx**2 + potBy**2 + potBz**2) + potBz == 0) then
      eigenvector(1,2,1) = 0
    else
      eigenvector(1,2,1) = (-potBx + i * potBy) / (-sqrt(potBx**2 + potBy**2 + potBz**2) + potBz)
    end if
    eigenvector(1,2,2) = 1

    eigenvector(2,1,1) = 0
    eigenvector(2,1,2) = 1

    eigenvector(2,2,1) = 1
    eigenvector(2,2,2) = 0

    eigenvector(3,1,1) = 0
    eigenvector(3,1,2) = 1

    eigenvector(3,2,1) = 1
    eigenvector(3,2,2) = 0

    if(sqrt(potBx**2 + potBy**2 + potBz**2) - potBz == 0) then
      eigenvector(4,1,1) = 0
    else
      eigenvector(4,1,1) = ( potBx - i * potBy) / ( sqrt(potBx**2 + potBy**2 + potBz**2) - potBz)
    end if
    eigenvector(4,1,2) = 1

    if(-sqrt(potBx**2 + potBy**2 + potBz**2) - potBz == 0) then
      eigenvector(4,2,1) = 0
    else
      eigenvector(4,2,1) = ( potBx - i * potBy) / (-sqrt(potBx**2 + potBy**2 + potBz**2) - potBz)
    end if
    eigenvector(4,2,2) = 1
  end if

  ! These eigenvectors are orthogonal, but not yet normalised
  ! normalisation:
  do matrixindex=1,4
  do eigenvalueindex = 1,2
    norm = 1.0d0
    if(eigenvector(matrixindex,eigenvalueindex,1) /= 0 .OR. eigenvector(matrixindex,eigenvalueindex,2) /= 0) then
      norm = sqrt(abs(eigenvector(matrixindex,eigenvalueindex,1))**2.0d0 + abs(eigenvector(matrixindex,eigenvalueindex,2))**2.0d0)
      eigenvector(matrixindex,eigenvalueindex,1) = eigenvector(matrixindex,eigenvalueindex,1) / norm
      eigenvector(matrixindex,eigenvalueindex,2) = eigenvector(matrixindex,eigenvalueindex,2) / norm
    end if
  end do
  end do
end subroutine SubMatrixEigenvector



subroutine getPotPhi(zatom,meshpoints,nr,theta,phi,VLLin,potPhi) 
! Sample potential
  use SpinSphericals
  use Constants
  implicit none
  double precision :: r,theta,phi,potPhi,V_spinup,V_spindown
  double precision :: zatom,meshpoints(:)
  integer          :: nr,lcut,l,m
  double precision :: VLLin(:,:,:) !VLLin(nrmax,(2*lcut+1)**2,2)
  integer          :: lmmax,lm,nrmax

  r = meshpoints(nr)
  lmmax=size(VLLin(1,:,1),1)
  nrmax=size(VLLin(:,1,1),1)
  lcut = int(1.0d0/2.0d0 * (sqrt(real(lmmax)) -1)) ! lmmax=(2*lcut+1)**2
  V_spindown = 0.0d0
  lm=1
  do l=0,2*lcut,1
  do m=-l,l,1
      if (lm==1) then
          ! Due to a strange convention the V00 component has a prefactor that the values for other l,m indices don't have
          V_spindown = V_spindown + sqrt(4.0d0*Pi) * VLLin(nr,lm,1) * RealSphericalHarmonic(l,m,theta,phi)
      else
          V_spindown = V_spindown +                  VLLin(nr,lm,1) * RealSphericalHarmonic(l,m,theta,phi)
      end if
      lm = lm+1
  end do
  end do
  V_spinup = 0.0d0
  lm=1
  do l=0,lcut,1
  do m=-l,l,1
      if (lm==1) then
          ! Due to a strange convention the V00 component has a prefactor that the values for other l,m indices don't have
          V_spinup = V_spinup + sqrt(4.0d0*Pi) * VLLin(nr,lm,2) * RealSphericalHarmonic(l,m,theta,phi)
      else
          V_spinup = V_spinup +                  VLLin(nr,lm,2) * RealSphericalHarmonic(l,m,theta,phi)
      end if
      lm = lm+1
  end do
  end do
  ! account for different convention in the Dirac solver:
  V_spindown = V_spindown / echarge 
  V_spinup   = V_spinup   / echarge
  ! calculate total potential:
  potPhi = - echarge / 4.0d0 / Pi / eps0 / r * zatom + 0.5d0 * (V_spindown + V_spinup)
end subroutine getPotPhi 

subroutine getPotB(zatom,meshpoints,nr,theta,phi,VLLin,potBx,potBy,potBz)
! Sample potential
  use SpinSphericals
  use Constants
  implicit none
  double precision                :: r,theta,phi,potBx,potBy,potBz,V_spinup,V_spindown
  double precision                :: zatom,meshpoints(:)
  integer                         :: nr,lcut,l,m
  double precision                :: VLLin(:,:,:)
  integer                         :: lmmax,lm,nrmax

  r = meshpoints(nr)
  lmmax=size(VLLin(1,:,1),1)
  nrmax=size(VLLin(:,1,1),1)
  lcut = int(1/2 * (sqrt(real(lmmax)) -1)) ! lmmax=(2*lcut+1)**2

  V_spindown = 0.0d0
  lm=1
  do l=0,lcut,1
  do m=-l,l,1
      if (lm==1) then
          ! Due to a strange convention the V00 component has a prefactor that the values for other l,m indices don't have
          V_spindown = V_spindown + sqrt(4.0d0*Pi) * VLLin(nr,lm,1) * RealSphericalHarmonic(l,m,theta,phi)
      else
          V_spindown = V_spindown +                  VLLin(nr,lm,1) * RealSphericalHarmonic(l,m,theta,phi)
      end if
      lm = lm+1
  end do
  end do
  V_spinup = 0.0d0
  lm=1
  do l=0,2*lcut,1
  do m=-l,l,1
      if (lm==1) then
          ! Due to a strange convention the V00 component has a prefactor that the values for other l,m indices don't have
          V_spinup = V_spinup + sqrt(4.0d0*Pi) * VLLin(nr,lm,2) * RealSphericalHarmonic(l,m,theta,phi)
      else
          V_spinup = V_spinup +                  VLLin(nr,lm,2) * RealSphericalHarmonic(l,m,theta,phi)
      end if
      lm = lm+1
  end do
  end do
  ! account for different convention in the Dirac solver:
  V_spindown = V_spindown / echarge 
  V_spinup   = V_spinup   / echarge

  potBx = 0
  potBy = 0
  potBz = 0.5d0 * (- V_spindown + V_spinup)
end subroutine getPotB 

integer function CheckExistence(filename)
  character(len=100), intent(in)  :: filename
  integer                         :: status
  open(unit=78, file=filename, status='old', action='read', iostat=status)
  if(status == 0) then
      ! file exists
      CheckExistence = 1
  else
      ! file does not exist
      CheckExistence = 0
  end if
  close(unit=78)
end function CheckExistence

complex (kind=dp) function GetNumberOfLines(filename)
! opens a file and finds out the number of lines
  use DiracConfig
  implicit none
  character(len=100), intent(in)  :: filename
  integer                         :: nvals
  integer                         :: status
  double precision                :: value

  nvals=0
  open(unit=77, file=filename, status='old', action='read', iostat=status)
  if(status == 0) then
      if(verbose > 1) then
          write(*,*) "successfully opened ", filename
      end if
      do
          read(77,*,iostat=status) value
          if(status /= 0) exit
          nvals = nvals + 1
      end do
      if(status > 0) then
          write(*,*) "an error occured while reading from ", filename
      else
          if(verbose > 1) then
              write(*,*) "the file ", filename, " has ", nvals, " lines "
          end if
      end if
  else
      write(*,*) "ERROR in GetNumberOfLines():"
      write(*,*) "could not open file ", filename
  end if
  GetNumberOfLines = nvals

  close(unit=77)
end function GetNumberOfLines

end module Potential