LCOV - code coverage report
Current view: top level - src/67_common - m_spin_current.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 94.3 % 265 250
Test Date: 2026-11-09 11:14:24 Functions: 100.0 % 2 2
Branches: 71.4 % 692 494

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_spin_current
       2                 :             : !! NAME
       3                 :             : !!  m_spin_current
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !!
       7                 :             : !!
       8                 :             : !! COPYRIGHT
       9                 :             : !! Copyright (C) 2005-2026 ABINIT group (Mver)
      10                 :             : !!  This file is distributed under the terms of the
      11                 :             : !!  GNU General Public License, see ~abinit/COPYING
      12                 :             : !!  or http://www.gnu.org/copyleft/gpl.txt .
      13                 :             : !!
      14                 :             : !! SOURCE
      15                 :             : 
      16                 :             : #if defined HAVE_CONFIG_H
      17                 :             : #include "config.h"
      18                 :             : #endif
      19                 :             : 
      20                 :             : #include "abi_common.h"
      21                 :             : 
      22                 :             : module m_spin_current
      23                 :             : 
      24                 :             :  use m_errors
      25                 :             :  use m_abicore
      26                 :             :  use m_splines
      27                 :             :  use m_hdr
      28                 :             :  use m_dtset
      29                 :             :  use m_dtfil
      30                 :             : 
      31                 :             :  use defs_datatypes, only : pseudopotential_type
      32                 :             :  use defs_abitypes, only : MPI_type
      33                 :             :  use m_io_tools,   only : open_file
      34                 :             :  use m_pptools,    only : printxsf
      35                 :             :  use m_geometry,   only : xred2xcart
      36                 :             :  use m_fftcore,    only : sphereboundary
      37                 :             :  use m_special_funcs,   only : gamma_function
      38                 :             :  use m_fft,            only : fourwf
      39                 :             : 
      40                 :             :  implicit none
      41                 :             : 
      42                 :             :  private
      43                 :             : !!***
      44                 :             : 
      45                 :             :  public :: spin_current
      46                 :             : !!***
      47                 :             : 
      48                 :             : contains
      49                 :             : !!***
      50                 :             : 
      51                 :             : !!****f* m_spin_current/spin_current
      52                 :             : !! NAME
      53                 :             : !! spin_current
      54                 :             : !!
      55                 :             : !! FUNCTION
      56                 :             : !!
      57                 :             : !! INPUTS
      58                 :             : !!  atindx(natom)=index table for atoms (see gstate.f)
      59                 :             : !!  atindx1(natom)=inverse of atindx
      60                 :             : !!  cg(2,mcg)=wavefunctions (may be read from disk instead of input)
      61                 :             : !!  dtfil <type(datafiles_type)>=variables related to files
      62                 :             : !!  dtset <type(dataset_type)>=all input variables in this dataset
      63                 :             : !!  eigen(mband*nkpt*nsppol)=array for holding eigenvalues (hartree)
      64                 :             : !!  gmet = reciprocal space metric
      65                 :             : !!  gprimd = dimensionful reciprocal space vectors
      66                 :             : !!  hdr <type(hdr_type)>=the header of wf, den and pot files
      67                 :             : !!  kg(3,mpw*mkmem)=reduced (integer) coordinates of G vecs in basis sphere
      68                 :             : !!  mcg=size of wave-functions array (cg) =mpw*nspinor*mband*mkmem*nsppol
      69                 :             : !!  mpi_enreg=information about MPI parallelization
      70                 :             : !!  nattyp(dtset%ntypat)=number of atoms of each type
      71                 :             : !!  nfftf = fft grid dimensions for fine grid
      72                 :             : !!  ph1d = phase factors in 1 radial dimension
      73                 :             : !!  psps <type(pseudopotential_type)>=variables related to pseudopotentials
      74                 :             : !!   | mpsang= 1+maximum angular momentum
      75                 :             : !!  rhog(2,nfftf)=Fourier transform of total electron density (including compensation density in PAW)
      76                 :             : !!  rhor(nfftf,nspden)=total electron density (including compensation density in PAW)
      77                 :             : !!  rmet = real space metric tensor
      78                 :             : !!  symrec(3,3,nsym)=symmetries in reciprocal space, reduced coordinates
      79                 :             : !!  ucvol = unit cell volume
      80                 :             : !!  wffnow=unit number for current wf disk file
      81                 :             : !!  ylm(mpw*mkmem,mpsang*mpsang*useylm)= real spherical harmonics for each G and k point
      82                 :             : !!  ylmgr(mpw*mkmem,3,mpsang*mpsang*useylm)= gradients of real spherical harmonics
      83                 :             : !!
      84                 :             : !! OUTPUT
      85                 :             : !!   only output to file
      86                 :             : !!
      87                 :             : !! SOURCE
      88                 :             : 
      89                 :           1 : subroutine spin_current(cg,dtfil,dtset,gprimd,hdr,kg,mcg,mpi_enreg,psps)
      90                 :             : 
      91                 :             : !Arguments ------------------------------------
      92                 :             : !scalars
      93                 :             : !integer,intent(in) :: nfftf
      94                 :             : !real(dp),intent(in) :: ucvol
      95                 :             :  integer,intent(in) :: mcg
      96                 :             :  type(MPI_type),intent(in) :: mpi_enreg
      97                 :             :  type(datafiles_type),intent(in) :: dtfil
      98                 :             :  type(dataset_type),intent(in) :: dtset
      99                 :             :  type(hdr_type),intent(inout) :: hdr
     100                 :             :  type(pseudopotential_type),intent(in) :: psps
     101                 :             : !type(wffile_type),intent(in) :: wffnow
     102                 :             : !arrays
     103                 :             : !integer,intent(in) :: atindx(dtset%natom),atindx1(dtset%natom)
     104                 :             :  integer,intent(in) :: kg(3,dtset%mpw*dtset%mkmem)
     105                 :             : !integer,intent(in) :: nattyp(dtset%ntypat)
     106                 :             : !integer,intent(in) :: symrec(3,3,dtset%nsym)
     107                 :             :  real(dp),intent(in) :: cg(2,mcg)
     108                 :             : !real(dp),intent(in) :: eigen(dtset%mband*dtset%nkpt*dtset%nsppol),gmet(3,3)
     109                 :             :  real(dp),intent(in) :: gprimd(3,3)
     110                 :             : !real(dp),intent(in) :: rhog(2,nfftf),rhor(nfftf,dtset%nspden)
     111                 :             : !real(dp),intent(in) :: rmet(3,3)
     112                 :             : !real(dp),intent(in) :: ylm(dtset%mpw*dtset%mkmem,psps%mpsang*psps%mpsang*psps%useylm)
     113                 :             : !real(dp),intent(in) :: ylmgr(dtset%mpw*dtset%mkmem,3,psps%mpsang*psps%mpsang*psps%useylm)
     114                 :             : !real(dp),intent(inout) :: ph1d(2,3*(2*dtset%mgfft+1)*dtset%natom)
     115                 :             : 
     116                 :             : !Local variables-------------------------------
     117                 :             : !scalars
     118                 :             :  integer :: cplex,fft_option,i1
     119                 :             :  integer :: i2,i3,iband,icartdir,icg,ig
     120                 :             :  integer :: ikg,ikpt,iocc,irealsp,ispindir,ispinor,ispinorp
     121                 :             :  integer :: npw
     122                 :             :  integer :: icplex
     123                 :             :  integer :: realrecip
     124                 :             :  integer :: iatom,spcur_unit
     125                 :             :  real(dp) :: prefact_nk
     126                 :             :  real(dp) :: rescale_current
     127                 :             :  character(len=500) :: message
     128                 :             :  character(len=fnlen) :: filnam
     129                 :             : !arrays
     130                 :           1 :  integer,allocatable :: gbound(:,:),kg_k(:,:)
     131                 :           1 :  real(dp),allocatable :: dpsidr(:,:,:,:,:,:)
     132                 :           1 :  real(dp),allocatable :: density(:,:,:,:)
     133                 :           1 :  real(dp),allocatable :: dummy_denpot(:,:,:)
     134                 :           1 :  real(dp),allocatable :: gpsi(:,:,:,:),kgcart(:,:)
     135                 :           1 :  real(dp),allocatable :: position_op(:,:,:,:)
     136                 :           1 :  real(dp),allocatable :: psi(:,:,:),psi_r(:,:,:,:,:)
     137                 :           1 :  real(dp),allocatable :: spincurrent(:,:,:,:,:)
     138                 :           1 :  real(dp),allocatable :: vso_realspace(:,:,:,:,:),datagrid(:)
     139                 :             :  real(dp) :: dummy_fofgout(0,0)
     140                 :           1 :  real(dp),allocatable :: xcart(:,:)
     141                 :             :  character :: spin_symbol(3)
     142                 :             :  character :: spinor_sym(2)
     143                 :             :  character(len=2) :: realimag(2)
     144                 :             : !no_abirules
     145                 :             : !real(dp),allocatable :: density_matrix(:,:,:,:,:)
     146                 :             : !real(dp),allocatable :: vso_realspace_nl(:,:,:,:,:)
     147                 :             : 
     148                 :             : ! *************************************************************************
     149                 :             : 
     150                 :             : !write(std_out,*) ' Entering subroutine spin_current '
     151                 :             : !write(std_out,*) ' dtset%ngfft = ', dtset%ngfft
     152                 :             : !write(std_out,*) ' hdr%istwfk = ', hdr%istwfk
     153                 :             : 
     154                 :             : !===================== init and checks ============================
     155                 :             : !check if nspinor is 2
     156         [ -  + ]:           1 :  if (dtset%nspinor /= 2) then
     157                 :           0 :    write(message, '(a,i0)' )' nspinor must be 2, but it is ',dtset%nspinor
     158                 :           0 :    ABI_ERROR(message)
     159                 :             :  end if
     160                 :             : 
     161         [ -  + ]:           1 :  if (dtset%nsppol /= 1) then
     162                 :           0 :    write(message, '(a,i0)' )' spin_current:  nsppol must be 1 but it is ',dtset%nsppol
     163                 :           0 :    ABI_ERROR(message)
     164                 :             :  end if
     165                 :             : 
     166         [ -  + ]:           1 :  if (dtset%mkmem /= dtset%nkpt) then
     167                 :             :    write(message, '(a,i6,a,i6,a,a)' )&
     168                 :           0 : &   ' mkmem =  ',dtset%mkmem,' must be equal to nkpt ',dtset%nkpt,ch10,&
     169                 :           0 : &   ' keep all kpt in memory'
     170                 :           0 :    ABI_ERROR(message)
     171                 :             :  end if
     172                 :             : 
     173         [ -  + ]:           1 :  if (dtset%usepaw /= 0) then
     174                 :             :    write(message, '(a,i0,a,a,a)' )&
     175                 :           0 : &   'usepaw =  ',dtset%usepaw,' must be equal to 0 ',ch10,&
     176                 :           0 : &   'Not functional for PAW case yet.'
     177                 :           0 :    ABI_ERROR(message)
     178                 :             :  end if
     179                 :             : 
     180                 :           1 :  cplex=2
     181                 :           1 :  fft_option = 0 ! just do direct fft
     182         [ +  + ]:           4 :  spin_symbol = (/'x','y','z'/)
     183         [ +  + ]:           3 :  spinor_sym = (/'u','d'/)
     184         [ +  + ]:           3 :  realimag = (/'Re','Im'/)
     185                 :             : 
     186                 :           1 :  write(std_out,*) ' psps%mpsang,psps%mpssoang ', psps%mpsang,psps%mpssoang
     187                 :             : 
     188                 :             : !======================= main code ================================
     189                 :             : !-----------------------------------------------------------------------------------------
     190                 :             : !-----------------------------------------------------------------------------------------
     191                 :             : !first get normal contribution to current, as psi tau dpsidr + dpsidr tau psi
     192                 :             : !where tau are 1/2 the pauli matrices
     193                 :             : !-----------------------------------------------------------------------------------------
     194                 :             : !-----------------------------------------------------------------------------------------
     195                 :             : 
     196                 :             : !init plane wave coeff counter
     197                 :           1 :  icg = 0
     198                 :             : !init plane wave counter
     199                 :           1 :  ikg = 0
     200                 :             : !init occupation/band counter
     201                 :           1 :  iocc = 1
     202                 :             : 
     203                 :             : !rspace point, cartesian direction, spin pol=x,y,z
     204   [ -  +  +  -  :           7 :  ABI_MALLOC(spincurrent,(dtset%ngfft(4),dtset%ngfft(5),dtset%ngfft(6),3,3))
          -  +  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
             -  -  +  -  
                      + ]
     205   [ +  +  +  +  :       32548 :  spincurrent = zero
          +  +  +  +  +  
                      + ]
     206                 :             : 
     207   [ -  +  +  -  :           5 :  ABI_MALLOC(dummy_denpot,(cplex*dtset%ngfft(4),dtset%ngfft(5),dtset%ngfft(6)))
          -  +  +  -  -  
          +  +  -  +  -  
          +  -  -  +  -  
                      + ]
     208                 :             : 
     209   [ +  -  -  +  :           4 :  ABI_MALLOC(gbound,(2*dtset%mgfft+8,2))
          +  -  +  -  +  
          -  +  -  -  +  
                   -  + ]
     210                 :             : 
     211                 :             : !allocate (density_matrix(2,dtset%ngfft(1)*dtset%ngfft(2)*dtset%ngfft(3),dtset%nspinor,&
     212                 :             : !&                           dtset%ngfft(1)*dtset%ngfft(2)*dtset%ngfft(3),dtset%nspinor))
     213                 :             : !density_matrix= zero
     214   [ -  +  +  -  :           5 :  ABI_MALLOC(density,(2,dtset%ngfft(1)*dtset%ngfft(2)*dtset%ngfft(3),dtset%nspinor,dtset%nspinor))
          -  +  +  -  -  
          +  +  -  +  -  
          +  -  -  +  -  
                      + ]
     215   [ +  +  +  +  :       40507 :  density= zero
             +  +  +  + ]
     216                 :             : 
     217   [ -  +  +  -  :           7 :  ABI_MALLOC(dpsidr,(2,dtset%ngfft(4),dtset%ngfft(5),dtset%ngfft(6),dtset%nspinor,3))
          -  +  +  -  -  
          +  +  -  -  +  
          +  -  +  -  +  
          -  +  -  -  +  
                   -  + ]
     218   [ -  +  +  -  :           6 :  ABI_MALLOC(psi_r,(2,dtset%ngfft(4),dtset%ngfft(5),dtset%ngfft(6),dtset%nspinor))
          -  +  +  -  -  
          +  +  -  -  +  
          +  -  +  -  +  
             -  -  +  -  
                      + ]
     219                 :             : 
     220                 :             : !loop over kpoints
     221         [ +  + ]:           2 :  do ikpt=1,dtset%nkpt
     222                 :             : 
     223                 :             : !  number of plane waves for this kpt
     224                 :           1 :    npw = hdr%npwarr(ikpt)
     225                 :             : 
     226                 :             : !  allocate arrays dep on number of pw
     227   [ -  +  +  -  :           3 :    ABI_MALLOC(kg_k,(3,npw))
          +  -  +  -  -  
                +  -  + ]
     228   [ -  +  +  -  :           5 :    ABI_MALLOC(gpsi,(2,npw,dtset%nspinor,3))
          -  +  +  -  +  
          -  +  -  +  -  
             -  +  -  + ]
     229   [ -  +  +  -  :           4 :    ABI_MALLOC(psi,(2,npw,dtset%nspinor))
          -  +  +  -  +  
          -  +  -  -  +  
                   -  + ]
     230   [ -  +  +  -  :           3 :    ABI_MALLOC(kgcart,(3,npw))
          +  -  +  -  -  
                +  -  + ]
     231                 :             : 
     232                 :             : !  get cartesian coordinates of k+G vectors around this kpoint
     233         [ +  + ]:         172 :    do ig=1,npw
     234   [ +  +  +  +  :        3249 :      kgcart(:,ig) = matmul(gprimd(:,:),dtset%kpt(:,ikpt)+kg(:,ikg+ig))
          +  +  +  +  +  
                      - ]
     235         [ +  + ]:         685 :      kg_k (:,ig) = kg(:,ikg+ig)
     236                 :             :    end do
     237                 :             : 
     238                 :             : !  get gbound
     239                 :           1 :    call sphereboundary(gbound,dtset%istwfk(ikpt),kg_k,dtset%mgfft,npw)
     240                 :             : 
     241                 :             : !  loop over bands
     242         [ +  + ]:          11 :    do iband=1,dtset%nband(ikpt)
     243                 :             : 
     244                 :             : !    prefactor for sum over bands and kpoints
     245                 :          10 :      prefact_nk = hdr%occ(iocc) * dtset%wtk(ikpt)
     246                 :             : 
     247                 :             : !    initialize this wf
     248   [ +  +  +  +  :       30880 :      gpsi=zero
             +  +  +  + ]
     249   [ +  +  +  +  :       10290 :      psi=zero
                   +  + ]
     250   [ +  +  +  + ]:        5140 :      psi(:,1:npw,1) = cg(:,icg+1:icg+npw)
     251                 :             : 
     252                 :             : !    multiply psi by - i 2 pi G
     253         [ +  + ]:        1720 :      do ig=1,npw
     254         [ +  + ]:        5130 :        gpsi(1,ig,:,1) =  two_pi * kgcart(1,ig)*psi(2,ig,:)
     255         [ +  + ]:        5130 :        gpsi(2,ig,:,1) = -two_pi * kgcart(1,ig)*psi(1,ig,:)
     256         [ +  + ]:        5130 :        gpsi(1,ig,:,2) =  two_pi * kgcart(2,ig)*psi(2,ig,:)
     257         [ +  + ]:        5130 :        gpsi(2,ig,:,2) = -two_pi * kgcart(2,ig)*psi(1,ig,:)
     258         [ +  + ]:        5130 :        gpsi(1,ig,:,3) =  two_pi * kgcart(3,ig)*psi(2,ig,:)
     259         [ +  + ]:        5140 :        gpsi(2,ig,:,3) = -two_pi * kgcart(3,ig)*psi(1,ig,:)
     260                 :             :      end do
     261                 :             : 
     262                 :             : !    loop over spinorial components
     263         [ +  + ]:          30 :      do ispinor=1,dtset%nspinor
     264                 :             : !      FT Gpsi_x to real space
     265                 :             :        call fourwf(cplex,dummy_denpot,gpsi(:,:,ispinor,1),dummy_fofgout,&
     266                 :             : &       dpsidr(:,:,:,:,ispinor,1),gbound,gbound,&
     267                 :             : &       hdr%istwfk(ikpt),kg_k,kg_k,dtset%mgfft,mpi_enreg,1,dtset%ngfft,npw,&
     268                 :             : &       npw,dtset%ngfft(4),dtset%ngfft(5),dtset%ngfft(6),&
     269                 :          20 : &       fft_option,0,one,one,gpu_option=dtset%gpu_option)
     270                 :             : 
     271                 :             : !      FT Gpsi_y to real space
     272                 :             :        call fourwf(cplex,dummy_denpot,gpsi(:,:,ispinor,2),dummy_fofgout,&
     273                 :             : &       dpsidr(:,:,:,:,ispinor,2),gbound,gbound,&
     274                 :             : &       hdr%istwfk(ikpt),kg_k,kg_k,dtset%mgfft,mpi_enreg,1,dtset%ngfft,npw,&
     275                 :             : &       npw,dtset%ngfft(4),dtset%ngfft(5),dtset%ngfft(6),&
     276                 :          20 : &       fft_option,0,one,one,gpu_option=dtset%gpu_option)
     277                 :             : 
     278                 :             : !      FT Gpsi_z to real space
     279                 :             :        call fourwf(cplex,dummy_denpot,gpsi(:,:,ispinor,3),dummy_fofgout,&
     280                 :             : &       dpsidr(:,:,:,:,ispinor,3),gbound,gbound,&
     281                 :             : &       hdr%istwfk(ikpt),kg_k,kg_k,dtset%mgfft,mpi_enreg,1,dtset%ngfft,npw,&
     282                 :             : &       npw,dtset%ngfft(4),dtset%ngfft(5),dtset%ngfft(6),&
     283                 :          20 : &       fft_option,0,one,one,gpu_option=dtset%gpu_option)
     284                 :             : 
     285                 :             : !      FT psi to real space
     286                 :             :        call fourwf(cplex,dummy_denpot,psi(:,:,ispinor),dummy_fofgout,&
     287                 :             : &       psi_r(:,:,:,:,ispinor),gbound,gbound,&
     288                 :             : &       hdr%istwfk(ikpt),kg_k,kg_k,dtset%mgfft,mpi_enreg,1,dtset%ngfft,npw,&
     289                 :             : &       npw,dtset%ngfft(4),dtset%ngfft(5),dtset%ngfft(6),&
     290                 :          30 : &       fft_option,0,one,one,gpu_option=dtset%gpu_option)
     291                 :             : 
     292                 :             :      end do ! ispinor
     293                 :             : 
     294                 :             : !    dpsidr now contains the full derivative of psi wrt space (gradient) in cartesian coordinates
     295                 :             : 
     296                 :             : !    get 3 pauli matrix contributions to the current: x,y,z, cart dir, spin dir
     297         [ +  + ]:          40 :      do icartdir=1,3
     298                 :             : 
     299                 :             : !      x pauli spin matrix
     300                 :             : !      sigma_x =  | 0   1 |
     301                 :             : !      | 1   0 |
     302                 :             :        spincurrent(:,:,:,icartdir,1) =  spincurrent(:,:,:,icartdir,1) + prefact_nk * &
     303                 :             : !      Re(psi_r(up)^* dpsidr(down))
     304                 :             : &       real(psi_r(1,:,:,:,1)*dpsidr(1,:,:,:,2,icartdir)  &
     305                 :             : &       + psi_r(2,:,:,:,1)*dpsidr(2,:,:,:,2,icartdir)  &
     306                 :             : !      Re(psi_r(down)^* dpsidr(up))
     307                 :             : &       + psi_r(1,:,:,:,2)*dpsidr(1,:,:,:,1,icartdir)  &
     308   [ +  +  +  +  :      108480 : &       + psi_r(2,:,:,:,2)*dpsidr(2,:,:,:,1,icartdir))
                   +  + ]
     309                 :             : 
     310                 :             : !      y pauli spin matrix
     311                 :             : !      sigma_y =  | 0  -i |
     312                 :             : !      | i   0 |
     313                 :             :        spincurrent(:,:,:,icartdir,2) =  spincurrent(:,:,:,icartdir,2) + prefact_nk * &
     314                 :             : !      Re(-i psi_r(up)^* dpsidr(down))
     315                 :             : &       real(psi_r(1,:,:,:,1)*dpsidr(2,:,:,:,2,icartdir)  &
     316                 :             : &       - psi_r(2,:,:,:,1)*dpsidr(1,:,:,:,2,icartdir)  &
     317                 :             : !      Re(i psi_r(down)^* dpsidr(up))
     318                 :             : &       - psi_r(1,:,:,:,2)*dpsidr(2,:,:,:,1,icartdir)  &
     319   [ +  +  +  +  :      108480 : &       + psi_r(2,:,:,:,2)*dpsidr(1,:,:,:,1,icartdir))
                   +  + ]
     320                 :             : 
     321                 :             : !      z pauli spin matrix
     322                 :             : !      sigma_z =  | 1   0 |
     323                 :             : !      | 0  -1 |
     324                 :             :        spincurrent(:,:,:,icartdir,3) =  spincurrent(:,:,:,icartdir,3) + prefact_nk * &
     325                 :             : !      Re(psi_r(up)^* dpsidr(up))
     326                 :             : &       real(psi_r(1,:,:,:,1)*dpsidr(1,:,:,:,1,icartdir)  &
     327                 :             : &       - psi_r(2,:,:,:,1)*dpsidr(2,:,:,:,1,icartdir)  &
     328                 :             : !      Re(-psi_r(down)^* dpsidr(down))
     329                 :             : &       - psi_r(1,:,:,:,2)*dpsidr(1,:,:,:,2,icartdir)  &
     330   [ +  +  +  +  :      108490 : &       + psi_r(2,:,:,:,2)*dpsidr(2,:,:,:,2,icartdir))
                   +  + ]
     331                 :             :      end do ! end icartdir
     332                 :             : 
     333                 :             : !
     334                 :             : !    accumulate non local density matrix in real space
     335                 :             : !    NOTE: if we are only using the local part of the current, this becomes the
     336                 :             : !    density spinor matrix! (much lighter to calculate) rho(r, sigma, sigmaprime)
     337                 :             : !
     338         [ +  + ]:          30 :      do ispinor=1,dtset%nspinor
     339         [ +  + ]:         330 :        do i3=1,dtset%ngfft(3)
     340         [ +  + ]:        4820 :          do i2=1,dtset%ngfft(2)
     341         [ +  + ]:       72300 :            do i1=1,dtset%ngfft(1)
     342                 :       67500 :              irealsp = i1 + (i2-1)*dtset%ngfft(1) + (i3-1)*dtset%ngfft(2)*dtset%ngfft(1)
     343                 :             : 
     344         [ +  + ]:      207000 :              do ispinorp=1,dtset%nspinor
     345                 :             :                density(1,irealsp,ispinor,ispinorp) = &
     346                 :             : &               density(1,irealsp,ispinor,ispinorp) + &
     347                 :             : &               prefact_nk * (psi_r(1,i1,i2,i3,ispinor)*psi_r(1,i1,i2,i3,ispinorp)&
     348                 :      135000 : &               +  psi_r(2,i1,i2,i3,ispinor)*psi_r(2,i1,i2,i3,ispinorp))
     349                 :             :                density(2,irealsp,ispinor,ispinorp) = &
     350                 :             : &               density(2,irealsp,ispinor,ispinorp) + &
     351                 :             : &               prefact_nk * (psi_r(1,i1,i2,i3,ispinor)*psi_r(2,i1,i2,i3,ispinorp)&
     352                 :      202500 : &               -  psi_r(2,i1,i2,i3,ispinor)*psi_r(1,i1,i2,i3,ispinorp))
     353                 :             : 
     354                 :             : !              do i3p=1,dtset%ngfft(3)
     355                 :             : !              do i2p=1,dtset%ngfft(2)
     356                 :             : !              do i1p=1,dtset%ngfft(1)
     357                 :             : !              irealsp_p = i1p + (i2p-1)*dtset%ngfft(1) + (i3p-1)*dtset%ngfft(2)*dtset%ngfft(1)
     358                 :             : !
     359                 :             : !              NOTE : sign changes in second terms below because rho = psi*(r) psi(rprime)
     360                 :             : !
     361                 :             : !              density_matrix(1,irealsp,ispinor,irealsp_p,ispinorp) = &
     362                 :             : !              &           density_matrix(1,irealsp,ispinor,irealsp_p,ispinorp) + &
     363                 :             : !              &           prefact_nk * (psi_r(1,i1,i2,i3,ispinor)*psi_r(1,i1p,i2p,i3p,ispinorp)&
     364                 :             : !              &           +  psi_r(2,i1,i2,i3,ispinor)*psi_r(2,i1p,i2p,i3p,ispinorp))
     365                 :             : !              density_matrix(2,irealsp,ispinor,irealsp_p,ispinorp) = &
     366                 :             : !              &           density_matrix(2,irealsp,ispinor,irealsp_p,ispinorp) + &
     367                 :             : !              &           prefact_nk * (psi_r(1,i1,i2,i3,ispinor)*psi_r(2,i1p,i2p,i3p,ispinorp)&
     368                 :             : !              &           -  psi_r(2,i1,i2,i3,ispinor)*psi_r(1,i1p,i2p,i3p,ispinorp))
     369                 :             : !              end do
     370                 :             : !              end do
     371                 :             : !              end do ! end irealspprime
     372                 :             : 
     373                 :             :              end do !end ispinorp do
     374                 :             : 
     375                 :             :            end do
     376                 :             :          end do
     377                 :             :        end do ! end irealsp
     378                 :             :      end do !end ispinor do
     379                 :             : 
     380                 :             : !    update pw counter
     381                 :          10 :      icg=icg+npw
     382                 :          11 :      iocc=iocc+1
     383                 :             :    end do ! iband
     384                 :             : 
     385                 :           1 :    ikg=ikg+npw
     386                 :             : 
     387                 :             : !  deallocate arrays dep on npw for this kpoint
     388         [ -  + ]:           1 :    ABI_FREE(kg_k)
     389         [ -  + ]:           1 :    ABI_FREE(gpsi)
     390         [ -  + ]:           1 :    ABI_FREE(psi)
     391         [ -  + ]:           2 :    ABI_FREE(kgcart)
     392                 :             : 
     393                 :             :  end do ! ikpt
     394                 :             : 
     395         [ -  + ]:           1 :  ABI_FREE(dpsidr)
     396         [ -  + ]:           1 :  ABI_FREE(psi_r)
     397         [ -  + ]:           1 :  ABI_FREE(dummy_denpot)
     398         [ -  + ]:           1 :  ABI_FREE(gbound)
     399                 :             : 
     400                 :             : !prefactor for contribution to spin current
     401                 :             : !prefactor is 1/2 * 1/2 * 2 Re(.):
     402                 :             : !1/2 from the formula for the current
     403                 :             : !1/2 from the use of the normalized Pauli matrices
     404                 :             : !2 from the complex conjugate part
     405                 :             : !total = 1/2
     406   [ +  +  +  +  :       32548 :  spincurrent = half * spincurrent
          +  +  +  +  +  
                      + ]
     407                 :             : 
     408                 :             : !make array of positions for all points on grid
     409   [ -  +  +  -  :           5 :  ABI_MALLOC(position_op,(3,dtset%ngfft(1),dtset%ngfft(2),dtset%ngfft(3)))
          -  +  +  -  -  
          +  +  -  +  -  
          +  -  -  +  -  
                      + ]
     410         [ +  + ]:          16 :  do i3=1,dtset%ngfft(3)
     411         [ +  + ]:         241 :    do i2=1,dtset%ngfft(2)
     412         [ +  + ]:        3615 :      do i1=1,dtset%ngfft(1)
     413                 :             :        position_op(:,i1,i2,i3) = matmul(hdr%rprimd,(/i1-one,i2-one,i3-one/))&
     414   [ +  +  +  +  :       74475 : &       /(/dtset%ngfft(1),dtset%ngfft(2),dtset%ngfft(3)/)
          +  +  +  +  +  
                      + ]
     415                 :             :      end do
     416                 :             :    end do
     417                 :             :  end do
     418                 :             : 
     419                 :             : !-----------------------------------------------------------------------------------------
     420                 :             : !-----------------------------------------------------------------------------------------
     421                 :             : !add electric field term to current. Non local term in case of pseudopotential SO
     422                 :             : !present theory is that it is equal to A(r,r') = (W_SO(r,r') + W_SO(r',r))
     423                 :             : !For the strictly local part of the current, this becomes 2 W_SO(r,r)
     424                 :             : !
     425                 :             : !W_SO is the prefactor in the spinorbit part of the potential, such that it
     426                 :             : !can be written V_SO = W_SO . p (momentum operator)
     427                 :             : !decomposed from V_SO = v_SO(r,r') L.S = v_SO(r,r') (rxp).S = v_SO(r,r') (Sxr).p
     428                 :             : !and ensuring symmetrization for the r operator wrt the two arguments of v_SO(r,r')
     429                 :             : !Hence:
     430                 :             : !W_SO(r,r) = v_SO(r,r) (Sxr)
     431                 :             : !-----------------------------------------------------------------------------------------
     432                 :             : !-----------------------------------------------------------------------------------------
     433                 :             : 
     434                 :             : !allocate (vso_realspace_nl(2,dtset%ngfft(1)*dtset%ngfft(2)*dtset%ngfft(3),dtset%nspinor,&
     435                 :             : !& dtset%ngfft(1)*dtset%ngfft(2)*dtset%ngfft(3),dtset%nspinor))
     436                 :             : 
     437                 :             : !call vso_realspace_nonlop(atindx,atindx1,dtfil,dtset,gmet,gprimd,hdr,kg,&
     438                 :             : !& mpi_enreg,nattyp,ph1d,position_op,psps,rmet,ucvol,vso_realspace_nl,ylm,ylmgr)
     439                 :             : !anticommutator of VSO with position operator
     440                 :             : !--- not needed in local spin current case ---
     441                 :             : 
     442   [ -  +  +  -  :           6 :  ABI_MALLOC(vso_realspace,(2,dtset%ngfft(1)*dtset%ngfft(2)*dtset%ngfft(3),dtset%nspinor,dtset%nspinor,3))
          -  +  +  -  -  
          +  +  -  +  -  
          +  -  +  -  -  
                +  -  + ]
     443                 :             : 
     444                 :           1 :  call vso_realspace_local(dtset,hdr,position_op,psps,vso_realspace)
     445                 :             : 
     446                 :             : 
     447                 :             : !multiply by density (or density matrix for nonlocal case)
     448                 :             : !and add to spin current
     449                 :             : 
     450                 :             : 
     451                 :             : 
     452         [ -  + ]:           1 :  ABI_FREE(density)
     453                 :             : 
     454                 :           1 :  realrecip = 0 ! real space for xsf output
     455   [ -  +  +  -  :           3 :  ABI_MALLOC(xcart,(3,dtset%natom))
          +  -  +  -  -  
                +  -  + ]
     456                 :           1 :  call xred2xcart(dtset%natom,hdr%rprimd,xcart,hdr%xred)
     457                 :             : 
     458                 :             : !-----------------------------------------------------------------------------------------
     459                 :             : !-----------------------------------------------------------------------------------------
     460                 :             : !output 3 components of current for each real space point
     461                 :             : !-----------------------------------------------------------------------------------------
     462                 :             : !-----------------------------------------------------------------------------------------
     463         [ +  + ]:           4 :  do ispindir=1, 3
     464                 :             : !  choose rescale_current such that the maximum current component printed out
     465                 :             : !  is 1 percent of lattice distance
     466                 :             : !  By default XCrysDen multiplies by 200 to get something comparable to a distance in real space.
     467   [ +  +  +  +  :       32547 :    rescale_current = maxval(abs(spincurrent(:, :, :, :, ispindir)))
          +  +  +  +  +  
             +  +  -  -  
                      + ]
     468         [ +  + ]:           3 :    if (abs(rescale_current) < tol8) then
     469                 :             :      rescale_current = one
     470                 :             :    else
     471                 :             :      rescale_current = 0.001_dp * sqrt(max(sum(hdr%rprimd(:,1)**2), &
     472   [ +  +  +  +  :          10 : &     sum(hdr%rprimd(:,2)**2), sum(hdr%rprimd(:,3)**2)))
                   +  + ]
     473                 :             :    end if
     474                 :             : 
     475         [ +  - ]:           3 :    filnam=trim(dtfil%fnameabo_spcur)//spin_symbol(ispindir)//".xsf"
     476         [ -  + ]:           3 :    if (open_file(filnam,message,newunit=spcur_unit,status='unknown') /= 0) then
     477                 :           0 :      ABI_ERROR(message)
     478                 :             :    end if
     479                 :             : 
     480                 :             : !  print header
     481                 :           3 :    write (spcur_unit,'(a)')          '#'
     482                 :           3 :    write (spcur_unit,'(a)')          '#  Xcrysden format file'
     483                 :           3 :    write (spcur_unit,'(a)')          '#  spin current density, for all real space points'
     484                 :           3 :    write (spcur_unit,'(a,3(I5,1x))') '#  fft grid is ', dtset%ngfft(1), dtset%ngfft(2), dtset%ngfft(3)
     485                 :           3 :    write (spcur_unit,'(a,a,a)')  '# ', spin_symbol(ispindir), '-spin current, full vector '
     486                 :             : 
     487                 :           3 :    write (spcur_unit,'(a)')  'ATOMS'
     488         [ +  + ]:           6 :    do iatom = 1, dtset%natom
     489                 :           6 :      write (spcur_unit,'(I4, 2x, 3(E16.6, 1x))') int(dtset%znucl(dtset%typat(iatom))), xcart(:,iatom)
     490                 :             :    end do
     491                 :             : 
     492         [ +  + ]:          48 :    do i3=1,dtset%ngfft(3)
     493         [ +  + ]:         723 :      do i2=1,dtset%ngfft(2)
     494         [ +  + ]:       10845 :        do i1=1,dtset%ngfft(1)
     495                 :       10125 :          write (spcur_unit,'(a, 3(E10.3),2x, 3(E20.10))') 'X ', &
     496         [ +  + ]:       51300 : &         position_op(:, i1, i2, i3), spincurrent(i1, i2, i3, :, ispindir)*rescale_current
     497                 :             :        end do
     498                 :             :      end do
     499                 :             :    end do
     500                 :           4 :    close (spcur_unit)
     501                 :             : 
     502                 :             :  end do ! end ispindir
     503                 :             : 
     504                 :             : !-----------------------------------------------------------------------------------------
     505                 :             : !-----------------------------------------------------------------------------------------
     506                 :             : !output 3 spin components of V_SO matrices, for each real space point
     507                 :             : !-----------------------------------------------------------------------------------------
     508                 :             : !-----------------------------------------------------------------------------------------
     509   [ -  +  +  -  :           3 :  ABI_MALLOC(datagrid, (dtset%ngfft(1)*dtset%ngfft(2)*dtset%ngfft(3)))
          +  -  +  -  -  
                +  -  + ]
     510                 :             : 
     511         [ +  + ]:           4 :  do ispindir=1,3
     512         [ +  + ]:          10 :    do icplex=1,2
     513         [ +  + ]:          21 :      do ispinor=1,dtset%nspinor
     514         [ +  + ]:          42 :        do ispinorp=1,dtset%nspinor
     515                 :             : 
     516                 :             : !        for the moment only print out if non zero
     517   [ +  +  +  + ]:       81024 :          if (abs(sum(vso_realspace(icplex, :, ispinor, ispinorp, ispindir))) < tol8) cycle
     518                 :             : 
     519                 :             :          filnam=trim(dtfil%fnameabo_vso)//"_spin_"//spin_symbol(ispindir)//"_"//&
     520         [ +  - ]:          12 : &         spinor_sym(ispinor)//spinor_sym(ispinorp)//"_"//realimag(icplex)//".xsf"
     521                 :             : 
     522         [ -  + ]:          12 :          if (open_file(filnam,message,newunit=spcur_unit,status='unknown') /= 0) then
     523                 :           0 :            ABI_ERROR(message)
     524                 :             :          end if
     525                 :             : 
     526                 :             :          ! print header
     527                 :          12 :          write (spcur_unit,'(a)')        '#'
     528                 :          12 :          write (spcur_unit,'(a)')        '#  Xcrysden format file'
     529                 :          12 :          write (spcur_unit,'(a)')        '#  spin-orbit potential (space diagonal), for all real space points'
     530                 :          12 :          write (spcur_unit,'(a)')        '#    Real part first, then imaginary part'
     531                 :          12 :          write (spcur_unit,'(a,3(I5,1x))') '#  fft grid is ', dtset%ngfft(1), dtset%ngfft(2),   dtset%ngfft(3)
     532                 :          12 :          write (spcur_unit,'(a,a,a)')    '# ', spin_symbol(ispindir), '-spin contribution '
     533                 :          12 :          write (spcur_unit,'(a,a,a)')    '# ', spinor_sym(ispinor)//spinor_sym(ispinorp), &
     534                 :          24 :              '-spin element of the spinor 2x2 matrix '
     535                 :          12 :          write (spcur_unit,'(a,a)')      '#  cart x     *  cart y    *  cart z    ***',&
     536                 :          24 : &         ' up-up component    *  up-down           * down-up          * down-down          '
     537                 :             : 
     538                 :             :          ! Build contiguous array
     539   [ -  +  +  + ]:       40524 :          datagrid = vso_realspace(icplex,:,ispinor, ispinorp, ispindir)
     540                 :             : 
     541                 :             :          call printxsf(dtset%ngfft(1),dtset%ngfft(2),dtset%ngfft(3),&
     542                 :             : &         datagrid,hdr%rprimd,(/zero,zero,zero/), dtset%natom, dtset%ntypat, &
     543                 :          12 : &         dtset%typat, xcart, dtset%znucl, spcur_unit,realrecip)
     544                 :             : 
     545                 :             : !
     546                 :             : !        NOTE: have chosen actual dims of grid (n123) instead of fft box, for which n45
     547                 :             : !        may be different
     548                 :             : !
     549                 :             : !        do i3_dum=1,dtset%ngfft(3)+1
     550                 :             : !        i3 = mod(i3_dum-1,dtset%ngfft(3)) + 1
     551                 :             : !        do i2_dum=1,dtset%ngfft(2)+1
     552                 :             : !        i2 = mod(i2_dum-1,dtset%ngfft(2)) + 1
     553                 :             : !        do i1_dum=1,dtset%ngfft(1)+1
     554                 :             : !        i1 = mod(i1_dum-1,dtset%ngfft(1)) + 1
     555                 :             : !
     556                 :             : !        irealsp = i1 + (i2-1)*dtset%ngfft(1) + (i3-1)*dtset%ngfft(2)*dtset%ngfft(1)
     557                 :             : !        write (spcur_unit,'(E20.10,1x)')&
     558                 :             : !        &      vso_realspace(icplex,irealsp,  ispinor, ispinorp, ispindir)
     559                 :             : !        end do
     560                 :             : !        end do
     561                 :             : !        end do
     562                 :             : 
     563                 :          36 :          close (spcur_unit)
     564                 :             : 
     565                 :             :        end do ! ispinorp
     566                 :             :      end do ! ispinor
     567                 :             :    end do ! icplex
     568                 :             :  end do ! end ispindir
     569                 :             : 
     570         [ -  + ]:           1 :  ABI_FREE(datagrid)
     571         [ -  + ]:           1 :  ABI_FREE(vso_realspace)
     572                 :             : !deallocate (vso_realspace_nl)
     573         [ -  + ]:           1 :  ABI_FREE(position_op)
     574         [ -  + ]:           1 :  ABI_FREE(spincurrent)
     575         [ -  + ]:           1 :  ABI_FREE(xcart)
     576                 :             : 
     577                 :           1 :  write(std_out,*) ' Exiting subroutine spin_current '
     578                 :             : 
     579                 :           1 : end subroutine spin_current
     580                 :             : !!***
     581                 :             : 
     582                 :             : !!****f* m_spin_current/vso_realspace_local
     583                 :             : !! NAME
     584                 :             : !!   vso_realspace_local
     585                 :             : !!
     586                 :             : !! FUNCTION
     587                 :             : !!  Calculate real space (local - (r,r)) values of the SO part of the
     588                 :             : !!  pseudopotential. Reconstructed explicitly in the HGH/GTH case.
     589                 :             : !!
     590                 :             : !! INPUTS
     591                 :             : !!
     592                 :             : !! OUTPUT
     593                 :             : !!
     594                 :             : !! SIDE EFFECTS
     595                 :             : !!
     596                 :             : !! NOTES
     597                 :             : !!
     598                 :             : !! SOURCE
     599                 :             : 
     600                 :           1 : subroutine vso_realspace_local(dtset,hdr,position_op,psps,vso_realspace)
     601                 :             : 
     602                 :             : !Arguments -------------------------------
     603                 :             :  type(hdr_type),intent(inout) :: hdr
     604                 :             :  type(dataset_type),intent(in) :: dtset
     605                 :             :  type(pseudopotential_type),intent(in) :: psps
     606                 :             :  real(dp),intent(in) :: position_op(3,dtset%ngfft(1),dtset%ngfft(2),dtset%ngfft(3))
     607                 :             :  real(dp),intent(out) :: vso_realspace(2,dtset%ngfft(1)*dtset%ngfft(2)*dtset%ngfft(3),&
     608                 :             : & dtset%nspinor,dtset%nspinor,3)
     609                 :             : 
     610                 :             : !Local variables -------------------------
     611                 :             : !scalars
     612                 :             :  integer :: i,j,l, lmax,ipsp,iatom, ir1,ir2,ir3
     613                 :             :  integer :: rcexponent,irealsp
     614                 :             :  integer :: nradgrid,iradgrid
     615                 :             :  real(dp) :: gammai, gammaj, relative_position(3), radial_cutoff, norm_rel_pos
     616                 :             :  real(dp) :: expfact,lfact, vso_interpol, x,y,z
     617                 :             : !arrays
     618                 :           2 :  real(dp) :: xcart(3,dtset%natom),splint_x(1),splint_y(1)
     619                 :           1 :  real(dp), allocatable :: radial_grid(:)
     620                 :           1 :  real(dp), allocatable :: prefact_ijl(:,:,:,:),tmpvso(:),tmpvso_pp(:)
     621                 :           1 :  real(dp), allocatable :: vso_radial(:,:),vso_radial_pp(:,:),tmp_spline(:)
     622                 :           1 :  real(dp), allocatable :: offdiag_l_fact(:,:,:),kpar_matrix(:,:)
     623                 :             : 
     624                 :             : ! *********************************************************************
     625                 :             : 
     626                 :             : !recalculate xcart (option = 1)
     627                 :           1 :  call xred2xcart(dtset%natom,hdr%rprimd,xcart,hdr%xred)
     628                 :             : 
     629                 :           1 :  lmax = psps%mpsang-1
     630                 :             : 
     631                 :             : !content of gth pseudo type:
     632                 :             : !These are {rloc, C(1...4)} coefficients for psppar(0, :, :) indices,
     633                 :             : !Followed by the h coefficients for psppar(1:2, 1:, :) indices.
     634                 :             : !size (0:2, 0:4, npsp)
     635                 :             : !potential radius r_l is in psppar(l+1,0,ipsp)
     636                 :             : !real(dp), pointer :: psppar(:, :, :)
     637                 :             : !The covalence radii for each pseudo (?) size (npsp)
     638                 :             : !real(dp), pointer :: radii_cov(:)
     639                 :             : !Cut-off radii for core part and long-range part.
     640                 :             : !radii_cf(:, 1) is for the long-range cut-off and
     641                 :             : !radii_cf(:, 2) is for the core cut-off.
     642                 :             : !size (npsp, 2)
     643                 :             : !real(dp), pointer :: radii_cf(:, :)
     644                 :             : !Spin orbit coefficients in HGH/GTH formats: k11p
     645                 :             : !etc... see psp3ini.F90
     646                 :             : !dimension = num l channels, 3 coeffs, num psp =
     647                 :             : !(1:lmax+1,1:3,npsp)
     648                 :             : !real(dp), pointer :: psp_k_par(:, :, :)
     649                 :             : 
     650                 :             : !v_SO^l (r,r') = sum_i sum_j sum_m Y_{lm} (\hat{r}) p_i^l (r) k_{ij}^l p_j^l(r') Y^{*}_lm (\hat{r'})
     651                 :             : !
     652                 :             : !v_SO^l (r,r)  = sum_ij  p_i^l (r) k_{ij}^l p_j^l(r) sum_m Y_{lm} (\hat{r}) Y^{*}_lm (\hat{r})
     653                 :             : != (2l+1)/4\pi sum_ij  p_i^l (r) k_{ij}^l p_j^l(r) (eq B.17 Patrick Rinke thesis)
     654                 :             : !p are gaussian projectors (from HGH paper prb 58 3641) [[cite:Hartwigsen1998]]
     655                 :             : !sum_l v_SO^l (r,r) is a purely radial quantity (function of |r|), so spline it
     656                 :             : 
     657                 :             : !maximum distance needed in unit cell
     658   [ +  +  +  +  :           7 :  radial_cutoff = four * maxval(psps%gth_params%psppar(:, 0, :))
          +  +  +  -  -  
                +  -  - ]
     659                 :             : 
     660                 :             : !setup radial grid; Should we use a logarithmic grid? The spline functions can
     661                 :             : !take it...
     662                 :           1 :  nradgrid = 201 ! this is heuristic
     663         [ -  + ]:           1 :  ABI_MALLOC(radial_grid,(nradgrid))
     664         [ +  + ]:         202 :  do iradgrid=1,nradgrid
     665                 :         202 :    radial_grid(iradgrid) = (iradgrid-1)*radial_cutoff/(nradgrid-1)
     666                 :             :  end do
     667                 :             : 
     668                 :             : !calculate prefactors independent of r
     669   [ -  +  +  -  :           4 :  ABI_MALLOC(prefact_ijl,(3,3,0:lmax,psps%npsp))
          -  +  +  -  +  
          -  +  -  -  +  
                   -  + ]
     670   [ -  +  +  -  :           3 :  ABI_MALLOC(offdiag_l_fact,(3,3,0:lmax))
          +  -  +  -  -  
                +  -  + ]
     671         [ -  + ]:           1 :  ABI_MALLOC(kpar_matrix,(3,3))
     672                 :             : 
     673                 :             : !these factors complete the full 3x3 matrix of k (or h) parameters for the
     674                 :             : !HGH pseudos
     675   [ +  +  +  +  :          40 :  offdiag_l_fact = zero
                   +  + ]
     676                 :             : !l=0
     677                 :           1 :  offdiag_l_fact(1,2,0) = -half*sqrt(three/five)
     678                 :           1 :  offdiag_l_fact(1,3,0) = half*sqrt(five/21._dp)
     679                 :           1 :  offdiag_l_fact(2,3,0) = -half*sqrt(100._dp/63._dp)
     680                 :             : !l=1
     681                 :           1 :  offdiag_l_fact(1,2,1) = -half*sqrt(five/seven)
     682                 :           1 :  offdiag_l_fact(1,3,1) = sixth*sqrt(35._dp/11._dp)
     683                 :           1 :  offdiag_l_fact(2,3,1) = -sixth*14._dp/sqrt(11._dp)
     684                 :             : !l=2
     685         [ +  - ]:           1 :  if (lmax >= 2) then
     686                 :           1 :    offdiag_l_fact(1,2,2) = -half*sqrt(seven/nine)
     687                 :           1 :    offdiag_l_fact(1,3,2) = half*sqrt(63._dp/143._dp)
     688                 :           1 :    offdiag_l_fact(2,3,2) = -half*18._dp /sqrt(143._dp)
     689                 :             :  end if
     690                 :             : !l=3
     691         [ -  + ]:           1 :  if (lmax >= 3) then
     692                 :           0 :    offdiag_l_fact(1,2,3) = zero
     693                 :           0 :    offdiag_l_fact(1,3,3) = zero
     694                 :           0 :    offdiag_l_fact(2,3,3) = zero
     695                 :             :  end if
     696                 :             : !get prefactors for evaluation of V_SO: terms that do not depend on r
     697   [ +  +  +  +  :          41 :  prefact_ijl = zero
             +  +  +  + ]
     698         [ +  + ]:           4 :  do l=0,lmax
     699                 :             : !  first the diagonal i=j term
     700         [ +  + ]:          12 :    do i=1,3
     701                 :           9 :      call gamma_function(l+(4._dp*i-1._dp)*0.5_dp, gammai)
     702                 :           9 :      gammai = sqrt(gammai)
     703                 :           9 :      rcexponent = 2*l+2*i+2*i-1
     704         [ +  + ]:          21 :      do ipsp=1,psps%npsp
     705                 :             :        prefact_ijl(i,i,l,ipsp) = psps%gth_params%psp_k_par(l+1,i,ipsp) &
     706                 :             : &       / ( (psps%gth_params%psppar(l+1,0,ipsp))**(rcexponent) &
     707                 :          18 : &       * gammai * gammai)
     708                 :             :      end do
     709                 :             :    end do
     710                 :             : !  now the off diagonal elements
     711         [ +  + ]:           6 :    do ipsp=1,psps%npsp
     712                 :           3 :      kpar_matrix(1,2) = offdiag_l_fact (1,2,l)* psps%gth_params%psp_k_par(l+1,2,ipsp)
     713                 :           3 :      kpar_matrix(2,1) = kpar_matrix(1,2)
     714                 :           3 :      kpar_matrix(1,3) = offdiag_l_fact (1,3,l)* psps%gth_params%psp_k_par(l+1,3,ipsp)
     715                 :           3 :      kpar_matrix(3,1) = kpar_matrix(1,3)
     716                 :           3 :      kpar_matrix(2,3) = offdiag_l_fact (2,3,l)* psps%gth_params%psp_k_par(l+1,3,ipsp)
     717                 :           6 :      kpar_matrix(3,2) = kpar_matrix(2,3)
     718                 :             :    end do
     719                 :             : 
     720                 :             : !  for the f case only the 1,1 matrix element is non 0 - it is done above and
     721                 :             : !  all these terms are actually 0
     722         [ +  - ]:           3 :    if (l > 2) cycle
     723                 :             : 
     724         [ +  + ]:          13 :    do i=1,3
     725                 :           9 :      call gamma_function(l+(4._dp*i-1._dp)*0.5_dp, gammai)
     726                 :           9 :      gammai = sqrt(gammai)
     727         [ +  + ]:          39 :      do j=1,3
     728         [ +  + ]:          27 :        if (j==i) cycle
     729                 :          18 :        rcexponent = 2*l+2*i+2*j-1
     730                 :          18 :        call gamma_function(l+(4._dp*j-1._dp)*0.5_dp,gammaj)
     731                 :          18 :        gammaj = sqrt(gammaj)
     732         [ +  + ]:          45 :        do ipsp=1,psps%npsp
     733                 :             :          prefact_ijl(i,j,l,ipsp) = kpar_matrix(i,j) &
     734                 :             : &         / ( (psps%gth_params%psppar(l+1,0,ipsp))**rcexponent &
     735                 :          45 : &         * gammai * gammaj )
     736                 :             :        end do
     737                 :             :      end do
     738                 :             :    end do
     739                 :             :  end do
     740                 :             : 
     741         [ -  + ]:           1 :  ABI_FREE(kpar_matrix)
     742                 :           1 :  ABI_FREE(offdiag_l_fact)
     743                 :             : 
     744   [ +  +  +  +  :          41 :  prefact_ijl = prefact_ijl * two
             +  +  +  + ]
     745                 :             : 
     746                 :             : !calculate v_SO on radial grid
     747                 :             : ! MGNAG Runtime Error: *** Arithmetic exception: Floating invalid operation - aborting
     748   [ -  +  +  -  :           3 :  ABI_MALLOC(vso_radial,(nradgrid,psps%npsp))
          +  -  +  -  -  
                +  -  + ]
     749   [ +  +  +  + ]:         203 :  vso_radial = zero
     750         [ +  + ]:           4 :  do l=0,lmax
     751                 :         606 :    lfact=(2._dp*l+1._dp)/four/pi
     752         [ +  + ]:         607 :    do iradgrid=1,nradgrid
     753                 :         603 :      norm_rel_pos = radial_grid(iradgrid)
     754         [ +  + ]:        1209 :      do ipsp=1,psps%npsp
     755                 :         603 :        expfact = exp(-norm_rel_pos**2 / (psps%gth_params%psppar(l+1,0,ipsp))**2)
     756                 :             : 
     757         [ +  + ]:        3015 :        do i=1,3
     758         [ +  + ]:        7839 :          do j=1,3
     759                 :        5427 :            rcexponent = 2*l +2*i+2*j-4
     760         [ +  + ]:        7236 :            if(prefact_ijl(i,j,l,ipsp)/=0) then !vz_d 0**0
     761                 :             :              vso_radial(iradgrid,ipsp) = vso_radial(iradgrid,ipsp) + &
     762                 :        1005 : &             prefact_ijl(i,j,l,ipsp)*(norm_rel_pos**rcexponent) * expfact
     763                 :             :            end if  !vz_d
     764                 :             :          end do ! j
     765                 :             :        end do ! i
     766                 :             :      end do ! ipsp
     767                 :             :    end do ! iradgrid
     768                 :             :  end do ! lmax
     769                 :             : 
     770                 :             : !spline v_SO(radial coord): get second derivative coefficients
     771   [ -  +  +  -  :           2 :  ABI_MALLOC(vso_radial_pp,(nradgrid,psps%npsp))
             -  +  -  + ]
     772                 :             : 
     773         [ -  + ]:           1 :  ABI_MALLOC(tmp_spline,(nradgrid))
     774         [ -  + ]:           1 :  ABI_MALLOC(tmpvso,(nradgrid))
     775         [ -  + ]:           1 :  ABI_MALLOC(tmpvso_pp,(nradgrid))
     776         [ +  + ]:           2 :  do ipsp=1,psps%npsp
     777   [ -  +  +  + ]:         203 :    tmpvso = vso_radial(:,ipsp)
     778                 :           1 :    call spline( radial_grid, tmpvso, nradgrid, zero, radial_grid(nradgrid), tmpvso_pp )
     779         [ +  + ]:         203 :    vso_radial_pp(:,ipsp) = tmpvso_pp
     780                 :             :  end do
     781         [ -  + ]:           1 :  ABI_FREE(tmp_spline)
     782         [ -  + ]:           1 :  ABI_FREE(tmpvso)
     783         [ -  + ]:           1 :  ABI_FREE(tmpvso_pp)
     784                 :             : 
     785                 :             : !to optimize this I should precalculate the distances which are actually needed by
     786                 :             : !symmetry, or only sum over irreducible points in space and use weights
     787                 :             : 
     788                 :             : !for each physical atom present in unit cell
     789   [ +  +  +  +  :      121522 :  vso_realspace = zero
          +  +  +  +  +  
                      + ]
     790         [ +  + ]:           2 :  do iatom=1,dtset%natom
     791                 :             : !  atom type will be dtset%typat(iatom)
     792                 :             : 
     793                 :             : !  for each point on grid
     794         [ +  + ]:          17 :    do ir3=1,dtset%ngfft(3)
     795         [ +  + ]:         241 :      do ir2=1,dtset%ngfft(2)
     796         [ +  + ]:        3615 :        do ir1=1,dtset%ngfft(1)
     797                 :        3375 :          irealsp = ir1 + (ir2-1)*dtset%ngfft(1) + (ir3-1)*dtset%ngfft(2)*dtset%ngfft(1)
     798                 :             : 
     799                 :             : !        relative position from atom to point
     800         [ +  + ]:       13500 :          relative_position = position_op(:,ir1,ir2,ir3) - xcart(:,iatom)
     801                 :        3375 :          x=relative_position(1)
     802                 :        3375 :          y=relative_position(2)
     803                 :        3375 :          z=relative_position(3)
     804                 :             : 
     805                 :             : !        calculate norm^2
     806                 :        3375 :          norm_rel_pos = relative_position(1)**2+relative_position(2)**2+relative_position(3)**2
     807                 :             : 
     808                 :             : !        if norm^2 is too large, skip this point
     809         [ +  + ]:        3375 :          if (norm_rel_pos > radial_cutoff*radial_cutoff) cycle
     810                 :             : 
     811                 :             : !        calculate norm
     812                 :         459 :          splint_x(1) = sqrt(norm_rel_pos)
     813                 :             : 
     814                 :             : !        spline interpolate vso only depends on position (through pos - atomic position)
     815                 :             :          call splint (nradgrid,radial_grid,vso_radial(:,dtset%typat(iatom)),&
     816                 :         459 : &         vso_radial_pp(:,dtset%typat(iatom)),1,splint_x,splint_y)
     817                 :         459 :          vso_interpol=splint_y(1)
     818                 :             : 
     819                 :             : !        multiply by vectorial spin factor (S x r)
     820                 :             : !        NOTE: this r is taken relative to atom center. It could be that the r operator should
     821                 :             : !        applied in an absolute way wrt the origin...
     822                 :             : !
     823                 :             : !        Is this correct: accumulated sum over atoms ?
     824                 :             :          vso_realspace(1,irealsp,:,:,1) = vso_realspace(1,irealsp,:,:,1) + &
     825   [ +  +  +  +  :        5049 : &         vso_interpol * reshape((/y,   zero,zero,-y/),(/2,2/))
                   +  + ]
     826                 :             :          vso_realspace(2,irealsp,:,:,1) = vso_realspace(2,irealsp,:,:,1) + &
     827   [ +  +  +  +  :        5049 : &         vso_interpol * reshape((/zero,z,  -z,    zero/),(/2,2/))
                   +  + ]
     828                 :             : 
     829                 :             :          vso_realspace(1,irealsp,:,:,2) = vso_realspace(1,irealsp,:,:,2) + &
     830   [ +  +  +  +  :        5049 : &         vso_interpol * reshape((/-x,  z,   z,   x/),(/2,2/))
                   +  + ]
     831                 :             :          vso_realspace(2,irealsp,:,:,2) = vso_realspace(2,irealsp,:,:,2) + &
     832   [ +  +  +  + ]:        3213 : &         vso_interpol * reshape((/zero,zero,zero,zero/),(/2,2/))
     833                 :             : 
     834                 :             :          vso_realspace(1,irealsp,:,:,3) = vso_realspace(1,irealsp,:,:,3) + &
     835   [ +  +  +  +  :        5049 : &         vso_interpol * reshape((/zero,-y, -y,   zero/),(/2,2/))
                   +  + ]
     836                 :             :          vso_realspace(2,irealsp,:,:,3) = vso_realspace(2,irealsp,:,:,3) + &
     837   [ +  +  +  +  :        8190 : &         vso_interpol * reshape((/zero,-x, -x,    zero/),(/2,2/))
                   +  + ]
     838                 :             : 
     839                 :             :        end do  ! ir3
     840                 :             :      end do  ! ir2
     841                 :             :    end do  ! ir1
     842                 :             :  end do ! iatom
     843                 :             : 
     844         [ -  + ]:           1 :  ABI_FREE(prefact_ijl)
     845         [ -  + ]:           1 :  ABI_FREE(vso_radial)
     846         [ -  + ]:           1 :  ABI_FREE(vso_radial_pp)
     847         [ -  + ]:           1 :  ABI_FREE(radial_grid)
     848                 :             : 
     849                 :           1 : end subroutine vso_realspace_local
     850                 :             : !!***
     851                 :             : 
     852                 :         171 : end module m_spin_current
     853                 :             : !!***
        

Generated by: LCOV version 2.3-1