LCOV - code coverage report
Current view: top level - src/72_response - m_dfpt_rhotov.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 76.9 % 389 299
Test Date: 2026-09-19 17:42:43 Functions: 100.0 % 4 4

            Line data    Source code
       1              : !!****m* ABINIT/m_dfpt_rhotov
       2              : !! NAME
       3              : !!  m_dfpt_rhotov
       4              : !!
       5              : !! FUNCTION
       6              : !!
       7              : !!
       8              : !! COPYRIGHT
       9              : !!  Copyright (C) 1999-2026 ABINIT group (XG, DRH, MT, SPr)
      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_dfpt_rhotov
      23              : 
      24              :  use defs_basis
      25              :  use m_abicore
      26              :  use m_errors
      27              :  use m_cgtools
      28              : 
      29              :  use defs_abitypes, only : MPI_type
      30              :  use m_time,        only : timab
      31              :  use m_spacepar,    only : hartrestr, hartre
      32              :  use m_dfpt_mkvxc,    only : dfpt_mkvxc, dfpt_mkvxc_noncoll
      33              :  use m_dfpt_mkvxcstr, only : dfpt_mkvxcstr
      34              :  use m_dens,        only : calcdenmagsph
      35              :  use m_numeric_tools, only : wrap2_zero_one
      36              : 
      37              :  implicit none
      38              : 
      39              :  private
      40              : !!***
      41              : 
      42              :  public :: dfpt_rhotov
      43              : !!***
      44              : 
      45              : contains
      46              : !!***
      47              : 
      48              : !!****f* ABINIT/dfpt_rhotov
      49              : !! NAME
      50              : !! dfpt_rhotov
      51              : !!
      52              : !! FUNCTION
      53              : !! This routine is called to compute, from a given 1st-order total density
      54              : !!   - the trial (local) 1st-order potential and/or the residual potential,
      55              : !!   - some contributions to the 2nd-order energy
      56              : !!
      57              : !! INPUTS
      58              : !!  cplex: if 1, real space 1-order WF on FFT grid are REAL; if 2, COMPLEX
      59              : !!  gsqcut=cutoff on (k+G)^2 (bohr^-2)
      60              : !!  icutcoul= type of Coulomb cutoff to apply
      61              : !!  idir=direction of atomic displacement (=1,2 or 3 : displacement of atom ipert along the 1st, 2nd or 3rd axis).
      62              : !!  ipert=type of the perturbation
      63              : !!  ixc= choice of exchange-correlation scheme
      64              : !!  kxc(nfft,nkxc)=exchange-correlation kernel
      65              : !!  mpi_enreg=information about MPI parallelization
      66              : !!  magpen=energy shift to apply on the spin degrees of freedom
      67              : !!  mpatpol(2)=initial and final atomic positions whose local magnetic moments will be penalized
      68              : !!  mpdir(3)=directions of the magnetic moments to be penalized
      69              : !!  natom=number of atoms in cell.
      70              : !!  nfft=(effective) number of FFT grid points (for this processor)
      71              : !!  ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft
      72              : !!  nhat(nfft,nspden*nhatdim)= -PAW only- compensation density
      73              : !!  nhat1(cplex*nfft,2nspden*usepaw)= -PAW only- 1st-order compensation density
      74              : !!  nhat1gr(cplex*nfft,nspden,3*nhat1grdim)= -PAW only- gradients of 1st-order compensation density
      75              : !!  nhat1grdim= -PAW only- 1 if nhat1gr array is used ; 0 otherwise
      76              : !!  nkxc=second dimension of the array kxc, see rhotoxc.f for a description
      77              : !!  non_magnetic_xc= if true, handle density/potential as non-magnetic (even if it is)
      78              : !!  nspden=number of spin-density components
      79              : !!  ntypat=number of atom types
      80              : !!  n3xccc=dimension of xccc3d1 ; 0 if no XC core correction is used
      81              : !!  optene=0: the contributions to the 2nd order energy are not computed
      82              : !!         1: the contributions to the 2nd order energy are computed
      83              : !!  optres=0: the trial potential residual is computed ; the input potential value is kept
      84              : !!         1: the new value of the trial potential is computed in place of the input value
      85              : !!  qphon(3)=reduced coordinates for the phonon wavelength
      86              : !!  ratopt=1: spheres around atoms are build in real space
      87              : !!         2: spheres around atoms are build in reciprocal space
      88              : !!  ratsm=smearing width for ratsph
      89              : !!  ratsph(ntypat)=radius of spheres around atoms
      90              : !!  rhog(2,nfft)=array for Fourier transform of GS electron density
      91              : !!  rhog1(2,nfft)=RF electron density in reciprocal space
      92              : !!  rhor(nfft,nspden)=array for GS electron density in electrons/bohr**3.
      93              : !!  rhor1(cplex*nfft,nspden)=RF electron density in real space (electrons/bohr**3).
      94              : !!  rprimd(3,3)=dimensional primitive translations in real space (bohr)
      95              : !!  typat(natom)=type of each atom
      96              : !!  ucvol=unit cell volume in ($\textrm{bohr}^{3}$)
      97              : !!  usepaw= 0 for non paw calculation; =1 for paw calculation
      98              : !!  usexcnhat= -PAW only- flag controling use of compensation density in Vxc
      99              : !!  vcutgeo(3)= array to describe the geometry of the Coulomb cutoff
     100              : !!  vpsp1(cplex*nfft)=first-order derivative of the ionic potential
     101              : !!  xccc3d1(cplex*n3xccc)=3D change in core charge density, see n3xccc
     102              : !!  xred(3,natom)=reduced dimensionless atomic coordinates
     103              : !!
     104              : !! OUTPUT
     105              : !!  vhartr1(cplex*nfft)=1-order Hartree potential (not output if size=0)
     106              : !!  vxc1(cplex*nfft,nspden)= 1st-order XC potential (not output if size=0)
     107              : !!  ==== if optene==1
     108              : !!    ehart01=inhomogeneous 1st-order Hartree part of 2nd-order total energy
     109              : !!    ehart1=1st-order Hartree part of 2nd-order total energy
     110              : !!    exc1=1st-order exchange-correlation part of 2nd-order total energy
     111              : !!    elpsp1=1st-order local pseudopot. part of 2nd-order total energy.
     112              : !!    emagpen1
     113              : !!  ==== if optres==0
     114              : !!    vresid1(cplex*nfft,nspden)=potential residual
     115              : !!    vres2=square of the norm of the residual
     116              : !!
     117              : !! SIDE EFFECTS
     118              : !!  ==== if optres==1
     119              : !!    vtrial1(cplex*nfft,nspden)= new value of 1st-order trial potential
     120              : !!
     121              : !! SOURCE
     122              : 
     123        21014 :  subroutine dfpt_rhotov(cplex,ehart01,ehart1,elmag1,elpsp1,emagpen1,exc1,gsqcut,icutcoul,idir,ipert,&
     124        21014 : &           ixc,kxc,magpen,mpatpol,mpdir,mpi_enreg,natom,nfft,ngfft,nhat,nhat1,nhat1gr,nhat1grdim,nkxc,nspden,ntypat,n3xccc,&
     125        21014 : &           non_magnetic_xc,optene,optres,qphon,ratsm,ratsph,rhog,rhog1,rhor,rhor1,rprimd,typat,ucvol,&
     126        21014 : &           usepaw,usexcnhat,vcutgeo,vhartr1,vpsp1,vresid1,vres2,vtrial1,vxc,vxc1,xccc3d1,ixcrot,xred,qgbt,use_gbt)
     127              : 
     128              : !Arguments ------------------------------------
     129              : !scalars
     130              :  integer,intent(in) :: cplex,icutcoul,idir,ipert,ixc,n3xccc,natom,nfft,nhat1grdim,nkxc,nspden
     131              :  integer,intent(in) :: ntypat,optene,optres,usepaw,usexcnhat,ixcrot
     132              :  logical,intent(in) :: non_magnetic_xc
     133              :  integer,intent(in) :: use_gbt
     134              :  real(dp),intent(in):: qgbt(3)
     135              :  real(dp),intent(in) :: gsqcut,magpen,ratsm,ucvol
     136              :  real(dp),intent(inout) :: ehart01,elpsp1,ehart1,exc1,elmag1,emagpen1
     137              :  real(dp),intent(out) :: vres2
     138              :  type(MPI_type),intent(in) :: mpi_enreg
     139              : !arrays
     140              :  integer,intent(in)   :: ngfft(18),typat(natom)
     141              :  integer,intent(in) :: mpatpol(2),mpdir(3)
     142              :  real(dp),intent(in) :: kxc(nfft,nkxc)
     143              :  real(dp),intent(in) :: vxc(nfft,nspden)
     144              :  real(dp),intent(in) :: nhat(nfft,nspden)
     145              :  real(dp),intent(in) :: nhat1(cplex*nfft,nspden)  !vz_d
     146              :  real(dp),intent(in) :: nhat1gr(cplex*nfft,nspden,3*nhat1grdim)
     147              :  real(dp),intent(in) :: qphon(3),ratsph(ntypat),rhog(2,nfft)
     148              :  real(dp),intent(in) :: rhog1(2,nfft)
     149              :  real(dp),target,intent(in) :: rhor(nfft,nspden),rhor1(cplex*nfft,nspden)
     150              :  real(dp),intent(in) :: rprimd(3,3),vpsp1(cplex*nfft)
     151              :  real(dp),intent(in) :: xccc3d1(cplex*n3xccc)
     152              :  real(dp),intent(inout) :: vtrial1(cplex*nfft,nspden)
     153              :  real(dp),intent(out) :: vresid1(cplex*nfft,nspden)
     154              :  real(dp),target,intent(out) :: vhartr1(:),vxc1(:,:)
     155              :  real(dp),intent(in) :: vcutgeo(3)
     156              :  real(dp),intent(in) :: xred(3,natom)
     157              : 
     158              : !Local variables-------------------------------
     159              : !scalars
     160              :  integer :: idir_eff,ifft,ispden,nfftot,option
     161              :  integer :: optnc,nkxc_cur,prtopt
     162              :  logical :: vhartr1_allocated,vxc1_allocated
     163              :  real(dp) :: doti,elpsp10
     164              : !arrays
     165              :  real(dp)             :: tsec(20)
     166        21014 :  real(dp),allocatable :: rhor1_nohat(:,:),vhartr01(:),vxc1val(:,:)
     167        21014 :  real(dp),pointer     :: rhor1_(:,:),vhartr1_(:),vxc1_(:,:),v1hspinfield(:,:)
     168        21014 :  real(dp),allocatable :: fatsph(:,:),intgden(:,:,:),rhomag(:,:),vmagpen1(:,:)
     169        21014 :  real(dp),allocatable :: taumr(:,:,:)
     170              : 
     171              : ! *********************************************************************
     172              : 
     173        21014 :  call timab(157,1,tsec)
     174              : 
     175              :  !FR EB SPr
     176        21014 :  if (nspden==4) then
     177          242 :    if(usepaw==1) then
     178            0 :      ABI_ERROR('DFPT with nspden=4 works only for norm-conserving psp!')
     179              :    end if
     180              :  end if
     181              : 
     182              : !Get size of FFT grid
     183        21014 :  nfftot=ngfft(1)*ngfft(2)*ngfft(3)
     184              : 
     185              : !Eventually allocate temporary memory space
     186        21014 :  vhartr1_allocated=(size(vhartr1)>0)
     187        21014 :  if (vhartr1_allocated) then
     188        21014 :    vhartr1_ => vhartr1
     189              :  else
     190            0 :    ABI_MALLOC(vhartr1_,(cplex*nfft))
     191              :  end if
     192        63042 :  vxc1_allocated=(size(vxc1)>0)
     193        21014 :  if (vxc1_allocated) then
     194        18718 :    vxc1_ => vxc1
     195              :  else
     196         9184 :    ABI_MALLOC(vxc1_,(cplex*nfft,nspden))
     197              :  end if
     198              : 
     199              : !If needed, store pseudo density without charge compensation
     200        21014 :  if (usepaw==1.and.usexcnhat==0) then
     201         7172 :    ABI_MALLOC(rhor1_,(cplex*nfft,nspden))
     202    134952082 :    rhor1_(:,:)=rhor1(:,:)-nhat1(:,:)
     203              :  else
     204        19221 :    rhor1_ => rhor1
     205              :  end if
     206              : 
     207              : !Uniform Zeeman or scalar potential
     208        21014 :  if(ipert==natom+5.or.ipert==natom+6)then
     209           82 :    if (ipert==natom+5) idir_eff= idir
     210           82 :    if (ipert==natom+6) idir_eff= 4
     211          328 :    ABI_MALLOC(v1hspinfield,(cplex*nfft,nspden))
     212           82 :    call dfpt_v1hspinfield(nspden,nfft,cplex,idir_eff,v1hspinfield)
     213              :  end if
     214              : 
     215              : !Preconditioned DFPT
     216        21014 :  if((ipert>natom+11.and.ipert<=2*natom+11).or.abs(magpen)>tol6) then
     217              : 
     218              :   !Compute the first-order magnetic moments.
     219           62 :    prtopt=1
     220          310 :    ABI_MALLOC(intgden,(cplex,nspden,natom))
     221          186 :    ABI_MALLOC(rhomag,(2,nspden))
     222          248 :    ABI_MALLOC(fatsph,(nfft,natom))
     223          310 :    ABI_MALLOC(taumr,(nfft,natom,3))
     224              :    call calcdenmagsph(mpi_enreg,natom,nfft,ngfft,nspden,&
     225              :   &  ntypat,ratsm,ratsph,rhor1,rprimd,typat,xred,prtopt,cplex,&
     226           62 :   &  qgbt,use_gbt,intgden=intgden,rhomag=rhomag,fatsph=fatsph,qphon=qphon,taumr=taumr)
     227              :  end if
     228              : 
     229        21014 :  if(ipert>natom+11.and.ipert<=2*natom+11)then
     230           68 :    ABI_MALLOC(v1hspinfield,(cplex*nfft,nspden))
     231              :    call dfpt_v1hspinfield_atsph(cplex,fatsph,idir,ipert,natom,nfft,nspden,&
     232           17 : &  qphon,taumr,v1hspinfield)
     233              :  end if
     234              : 
     235        84056 :  ABI_MALLOC(vmagpen1,(cplex*nfft,nspden))
     236    296720089 :  vmagpen1=zero
     237        21014 :  if (abs(magpen) > tol6) then
     238              :    call dfpt_v1magpen(cplex,emagpen1,fatsph,intgden,magpen,mpatpol,&
     239           62 : & mpdir,natom,nfft,nspden,qphon,rhomag,taumr,vmagpen1)
     240              :  end if
     241              : 
     242              : !------ Compute 1st-order Hartree potential (and energy) ----------------------
     243        21014 :  call hartre(cplex,gsqcut,icutcoul,0,mpi_enreg,nfft,ngfft,1,zero,rhog1,rprimd,vcutgeo,vhartr1_,qpt=qphon)
     244              : 
     245        21014 :  if (optene>0) then
     246        18505 :    call dotprod_vn(cplex,rhor1,ehart1,doti,nfft,nfftot,1,1,vhartr1_,ucvol)
     247              :  end if
     248              : 
     249        21014 :  if (optene>0) ehart01=zero
     250        21014 :  if(ipert==natom+3 .or. ipert==natom+4) then
     251         5025 :    ABI_MALLOC(vhartr01,(cplex*nfft))
     252         1675 :    call hartrestr(gsqcut,idir,ipert,mpi_enreg,natom,nfft,ngfft,rhog,rprimd,vhartr01)
     253         1675 :    if (optene>0) then
     254         1507 :      call dotprod_vn(cplex,rhor1,ehart01,doti,nfft,nfftot,1,1,vhartr01,ucvol)
     255         1507 :      ehart01=two*ehart01
     256         1507 :      ehart1=ehart1+ehart01
     257              :    end if
     258              : !  Note that there is a factor 2.0_dp difference with the similar GS formula
     259     11099319 :    vhartr1_(:)=vhartr1_(:)+vhartr01(:)
     260              : 
     261         1675 :    ABI_FREE(vhartr01)
     262              :  end if
     263              : 
     264              : !------ Compute 1st-order XC potential (and energy) ----------------------
     265              : !(including the XC core correction)
     266              : 
     267              : !Compute Vxc^(1) (with or without valence contribution according to options)
     268        21014 :  option=0;if (optene==0) option=1
     269        21014 :  if(ipert==natom+3.or.ipert==natom+4) then
     270              :    call dfpt_mkvxcstr(cplex,idir,ipert,kxc,mpi_enreg,natom,nfft,ngfft,nhat,&
     271              : &   nhat1,nkxc,non_magnetic_xc,nspden,n3xccc,option,qphon,rhor,rhor1,rprimd,&
     272         1675 : &   usepaw,usexcnhat,vxc1_,xccc3d1)
     273              :  else
     274              : ! FR EB non-collinear magnetism
     275              : ! the second nkxc should be nkxc_cur (see 67_common/nres2vres.F90)
     276        19339 :    if (nspden==4) then
     277          242 :      optnc=1
     278          242 :      nkxc_cur=nkxc ! TODO: remove nkxc_cur?
     279      8435350 :      vxc1_=zero
     280              : 
     281              :      call dfpt_mkvxc_noncoll(cplex,ixc,kxc,mpi_enreg,nfft,ngfft,nhat,usepaw,nhat1,usepaw,nhat1gr,nhat1grdim,nkxc,&
     282          242 : &     non_magnetic_xc,nspden,n3xccc,optnc,option,qphon,rhor,rhor1,rprimd,usexcnhat,vxc,vxc1_,xccc3d1,ixcrot=ixcrot)
     283              : 
     284              :    else
     285              :      call dfpt_mkvxc(cplex,ixc,kxc,mpi_enreg,nfft,ngfft,nhat1,usepaw,nhat1gr,nhat1grdim,nkxc,&
     286        19097 : &     non_magnetic_xc,nspden,n3xccc,option,qphon,rhor1,rprimd,usexcnhat,vxc1_,xccc3d1)
     287              :    end if !nspden==4
     288              :  end if
     289              : 
     290              : !Compute local contribution to 2nd-order energy (includes Vxc and Vpsp and Vmag)
     291        21014 :  if (optene>0) then
     292        18505 :    if (usepaw==0) then
     293        15059 :      call dotprod_vn(cplex,rhor1,elpsp10,doti,nfft,nfftot,nspden,1,vxc1_,ucvol)
     294        15059 :      call dotprod_vn(cplex,rhor1,elpsp1 ,doti,nfft,nfftot,1     ,1,vpsp1,ucvol)
     295        15059 :      if (ipert==natom+5.or.ipert==natom+6.or.(ipert>natom+11.and.ipert<=2*natom+11)) then
     296           87 :        call dotprod_vn(cplex,rhor1,elmag1 ,doti,nfft,nfftot,nspden,1,v1hspinfield,ucvol)
     297              :        !A factor of four, present in <0|H^1|1> terms, compensates the missing
     298              :        !half factor
     299           87 :        elmag1=two*elmag1
     300              :      end if
     301              :    else
     302         3446 :      if (usexcnhat/=0) then
     303         6237 :        ABI_MALLOC(rhor1_nohat,(cplex*nfft,1))
     304     28858687 :        rhor1_nohat(:,1)=rhor1(:,1)-nhat1(:,1)
     305         2079 :        call dotprod_vn(cplex,rhor1      ,elpsp10,doti,nfft,nfftot,nspden,1,vxc1_,ucvol)
     306         2079 :        call dotprod_vn(cplex,rhor1_nohat,elpsp1 ,doti,nfft,nfftot,1     ,1,vpsp1,ucvol)
     307         2079 :        ABI_FREE(rhor1_nohat)
     308              :      else
     309         1367 :        call dotprod_vn(cplex,rhor1_,elpsp10,doti,nfft,nfftot,nspden,1,vxc1_,ucvol)
     310         1367 :        call dotprod_vn(cplex,rhor1_,elpsp1 ,doti,nfft,nfftot,1     ,1,vpsp1,ucvol)
     311              :      end if
     312              :    end if
     313              : 
     314              : !  Note that there is a factor 2 difference with the similar GS formula
     315        18505 :    elpsp1=two*(elpsp1+elpsp10)
     316              :  end if
     317              : 
     318              : 
     319              : !Compute XC valence contribution exc1 and complete eventually Vxc^(1)
     320        21014 :  if (optene>0) then
     321        55515 :    ABI_MALLOC(vxc1val,(cplex*nfft,nspden))
     322    264248609 :    vxc1val=zero
     323        18505 :    option=2
     324              : !FR SPr EB non-collinear magnetism
     325        18505 :    if (nspden==4) then
     326          215 :      optnc=1
     327          215 :      nkxc_cur=nkxc
     328              :      call dfpt_mkvxc_noncoll(cplex,ixc,kxc,mpi_enreg,nfft,ngfft,nhat,usepaw,nhat1,usepaw,nhat1gr,nhat1grdim,nkxc,&
     329          215 : &     non_magnetic_xc,nspden,n3xccc,optnc,option,qphon,rhor,rhor1,rprimd,usexcnhat,vxc,vxc1val,xccc3d1,ixcrot=ixcrot)
     330              :    else
     331              :      call dfpt_mkvxc(cplex,ixc,kxc,mpi_enreg,nfft,ngfft,nhat1,usepaw,nhat1gr,nhat1grdim,nkxc,&
     332        18290 : &     non_magnetic_xc,nspden,n3xccc,option,qphon,rhor1,rprimd,usexcnhat,vxc1val,xccc3d1)
     333              :    end if !nspden==4
     334              : 
     335    264248609 :    vxc1_(:,:)=vxc1_(:,:)+vxc1val(:,:)
     336        18505 :    call dotprod_vn(cplex,rhor1_,exc1,doti,nfft,nfftot,nspden,1,vxc1val,ucvol)
     337        18505 :    ABI_FREE(vxc1val)
     338              :  end if
     339              : 
     340        21014 :  if (usepaw==1.and.usexcnhat==0) then
     341         1793 :    ABI_FREE(rhor1_)
     342              :  end if
     343              : 
     344              : !DEBUG (do not take away)
     345              : !Compute NSC energy ensc1 associated with rhor1 in vtrial1, for debugging purposes
     346              : !call dotprod_vn(cplex,rhor1,ensc1,doti,nfft,nfftot,nspden,1,vtrial1,ucvol)
     347              : !write(std_out,*)' ek0+eeig0+eloc0=',ek0+eeig0+eloc0
     348              : !write(std_out,*)' ensc1=',ensc1
     349              : !Compute NSC energy associated with vtrial1, for debugging purposes
     350              : !call dotprod_vn(cplex,rhor1,ensc1,doti,mpi_enreg,nfft,nfftot,nspden,1,vtrial1,ucvol)
     351              : !ensc1=ensc1+half*enl1
     352              : !write(std_out,*)' dfpt_rhotov : check NSC energy, diff=',&
     353              : !&  ek0+edocc+eeig0+eloc0+enl0+ensc1
     354              : !write(std_out,*)' evarNSC=',ek0+edocc+eeig0+eloc0+enl0
     355              : !write(std_out,*)' ensc1,exc1=',ensc1,exc1
     356              : !ENDDEBUG
     357              : 
     358              : !Here, vhartr1 contains Hartree potential, vpsp1 contains local psp,
     359              : !while vxc1 contain xc potential
     360              : 
     361              : !------ Produce residual vector and square of norm of it -------------
     362              : !(only if requested ; if optres==0)
     363        21014 :  if (optres==0) then
     364              : !$OMP PARALLEL DO COLLAPSE(2)
     365        38514 :    do ispden=1,min(nspden,2)
     366    258503231 :      do ifft=1,cplex*nfft
     367    258484850 :        vresid1(ifft,ispden)=vhartr1_(ifft)+vxc1_(ifft,ispden)+vpsp1(ifft)-vtrial1(ifft,ispden)
     368              :      end do
     369              :    end do
     370        18381 :    if(nspden==4)then
     371              : !$OMP PARALLEL DO COLLAPSE(2)
     372          645 :      do ispden=3,4
     373      3822669 :        do ifft=1,cplex*nfft
     374      3822454 :          vresid1(ifft,ispden)=vxc1_(ifft,ispden)-vtrial1(ifft,ispden)
     375              :        end do
     376              :      end do
     377              :    end if
     378              : 
     379        18381 :    if (ipert==natom+5.or.ipert==natom+6.or.(ipert>natom+11.and.ipert<=2*natom+11)) then
     380      4746123 :      vresid1 = vresid1 + v1hspinfield
     381              :    end if
     382              : 
     383        18381 :    if (abs(magpen) > tol6) then
     384       891135 :      vresid1 = vresid1 + vmagpen1
     385              :    end if
     386              : 
     387              : !  Compute square norm vres2 of potential residual vresid
     388        18381 :    call sqnorm_v(cplex,nfft,vres2,nspden,optres,vresid1)
     389              : 
     390              :  else
     391              : 
     392              : !  ------ Produce new value of trial potential-------------
     393              : !  (only if requested ; if optres==1)
     394              : 
     395              : !$OMP PARALLEL DO COLLAPSE(2)
     396         5706 :    do ispden=1,min(nspden,2)
     397     33999304 :      do ifft=1,cplex*nfft
     398     33996671 :        vtrial1(ifft,ispden)=vhartr1_(ifft)+vxc1_(ifft,ispden)+vpsp1(ifft)+vmagpen1(ifft,ispden)
     399              :      end do
     400              :    end do
     401         2633 :    if(nspden==4)then
     402              : !$OMP PARALLEL DO COLLAPSE(2)
     403           81 :      do ispden=3,4
     404       395127 :        do ifft=1,cplex*nfft
     405       395100 :          vtrial1(ifft,ispden)=vxc1_(ifft,ispden)+vmagpen1(ifft,ispden)
     406              :        end do
     407              :      end do
     408              :    end if
     409              : 
     410         2633 :    if (ipert==natom+5.or.ipert==natom+6.or.(ipert>natom+11.and.ipert<=2*natom+11)) then
     411       490808 :      vtrial1 = vtrial1 + v1hspinfield
     412              :    end if
     413              : 
     414         2633 :    if (abs(magpen) > tol6) then
     415       184375 :      vtrial1 = vtrial1 + vmagpen1
     416              :    end if
     417              : 
     418              :  end if
     419              : 
     420              : !Release temporary memory space
     421        21014 :  if (.not.vhartr1_allocated) then
     422            0 :    ABI_FREE(vhartr1_)
     423              :  end if
     424        21014 :  if (.not.vxc1_allocated) then
     425         2296 :    ABI_FREE(vxc1_)
     426              :  end if
     427              : 
     428        21014 :  if (ipert==natom+5.or.ipert==natom+6.or.(ipert>natom+11.and.ipert<=2*natom+11)) then
     429           99 :    ABI_FREE(v1hspinfield)
     430              :  end if
     431              : 
     432        21014 :  ABI_FREE(vmagpen1)
     433        21014 :  if((ipert>natom+11.and.ipert<=2*natom+11).or.abs(magpen)>tol6) then
     434           62 :    ABI_FREE(intgden)
     435           62 :    ABI_FREE(rhomag)
     436           62 :    ABI_FREE(fatsph)
     437           62 :    ABI_FREE(taumr)
     438              :  endif
     439              : 
     440        21014 :  call timab(157,2,tsec)
     441              : 
     442        42028 : end subroutine dfpt_rhotov
     443              : !!***
     444              : 
     445              : !!****f* ABINIT/dfpt_v1hspinfield
     446              : !! NAME
     447              : !!  dfpt_v1hspinfield
     448              : !!
     449              : !! FUNCTION
     450              : !!  Calculate 1st order spin magnetic (hspinfield) potential = -vec{\sigma}.\vec{b}, where
     451              : !!  sigma is the vector of Pauli matrices and \vec{b} is the unit
     452              : !!  vector indicating the perturbing field direction.
     453              : !!
     454              : !! INPUTS
     455              : !!  nspden = number of density matrix components
     456              : !!  nfft   = numbder of fft grid points
     457              : !!  cplex  = complex or real density matrix
     458              : !!  idir   = direction of the perturbing field in Cartesian frame
     459              : !!           1: along x
     460              : !!           2: along y
     461              : !!           3: along z
     462              : !!           4: identity matrix at each fft point is returned (for density-density response)
     463              : !!
     464              : !! OUTPUT
     465              : !!  v1hspinfield(nfft*cplex,nspden)= 1st order spin magnetic (hspinfield) potential, or Identity matrix (electrostatic potential) for idir=4
     466              : !!
     467              : !! SIDE EFFECTS
     468              : !!
     469              : !! NOTES
     470              : !!  The definition of components of the potential matrix differ depending on cplex
     471              : !!  for nspden=4:
     472              : !!  For cplex=1, the potential is defined as (V_upup,V_dndn,Re[V_updn],Im[V_updn])
     473              : !!  For cplex=2, the definition is (V_upup,V_dndn,V_updn,i.V_updn)
     474              : !!
     475              : !! SOURCE
     476              : 
     477           82 : subroutine dfpt_v1hspinfield(nspden,nfft,cplex,idir,v1hspinfield)
     478              : 
     479              : !Arguments ------------------------------------
     480              :  integer , intent(in)    :: idir,nfft,cplex,nspden
     481              :  real(dp), intent(inout) :: v1hspinfield(cplex*nfft,nspden)
     482              : 
     483              : !Local variables-------------------------------
     484              :  integer :: ifft
     485              : !character(len=500) :: msg
     486              : 
     487              : ! *************************************************************************
     488              : 
     489              :  DBG_ENTER("COLL")
     490              : 
     491              : ! if (option/=1 .and. option/=2 ) then
     492              : !   write(msg,'(3a,i0)')&
     493              : !&   'The argument option should be 1 or 2,',ch10,&
     494              : !&   'however, option=',option
     495              : !   ABI_BUG(msg)
     496              : ! end if
     497              : !
     498              : ! if (sizein<1) then
     499              : !   write(msg,'(3a,i0)')&
     500              : !&   'The argument sizein should be a positive number,',ch10,&
     501              : !&   'however, sizein=',sizein
     502              : !   ABI_ERROR(msg)
     503              : ! end if
     504              : 
     505              :  DBG_EXIT("COLL")
     506              : 
     507           24 :  select case(cplex)
     508              :  case(1)
     509           24 :    if (nspden==4) then
     510            2 :      if(idir==3)then       ! Zeeman field along the 3rd axis (z)
     511            0 :        v1hspinfield(:,1)=-0.5d0
     512            0 :        v1hspinfield(:,2)=+0.5d0
     513            0 :        v1hspinfield(:,3)= 0.0d0
     514            0 :        v1hspinfield(:,4)= 0.0d0
     515            2 :      else if(idir==2)then  ! Zeeman field along the 2nd axis (y)
     516            0 :        v1hspinfield(:,1)= 0.0d0
     517            0 :        v1hspinfield(:,2)= 0.0d0
     518            0 :        v1hspinfield(:,3)= 0.0d0
     519            0 :        v1hspinfield(:,4)=+0.5d0
     520            2 :      else if(idir==1)then  ! Zeeman field along the 1st axis (x)
     521         5122 :        v1hspinfield(:,1)= 0.0d0
     522         5122 :        v1hspinfield(:,2)= 0.0d0
     523         5122 :        v1hspinfield(:,3)=-0.5d0
     524         5122 :        v1hspinfield(:,4)= 0.0d0
     525            0 :      else if(idir==4)then  ! Scalar potential
     526            0 :        v1hspinfield(:,1)=-1.0d0
     527            0 :        v1hspinfield(:,2)=-1.0d0
     528            0 :        v1hspinfield(:,3)= 0.0d0
     529            0 :        v1hspinfield(:,4)= 0.0d0
     530              :      end if
     531           22 :    else if (nspden==2) then
     532           22 :      if (idir==4) then
     533            0 :        v1hspinfield(:,1)=-0.5d0
     534            0 :        v1hspinfield(:,2)=-0.5d0
     535              :      else
     536       176022 :        v1hspinfield(:,1)=-0.5d0
     537       176022 :        v1hspinfield(:,2)= 0.5d0
     538              :      end if
     539              :    else
     540            0 :      v1hspinfield(:,1)= 0.0d0
     541              :    end if
     542              :  case(2)
     543           82 :    if (nspden==2) then
     544            0 :      if (idir==4) then
     545            0 :        do ifft=1,nfft
     546            0 :          v1hspinfield(2*ifft-1,1)  =-0.5e0
     547            0 :          v1hspinfield(2*ifft  ,1)  = 0.0e0
     548            0 :          v1hspinfield(2*ifft-1,2)  =-0.5e0
     549            0 :          v1hspinfield(2*ifft  ,2)  = 0.0e0
     550              :        end do
     551              :      else
     552            0 :        do ifft=1,nfft
     553            0 :          v1hspinfield(2*ifft-1,1)  =-0.5e0
     554            0 :          v1hspinfield(2*ifft  ,1)  = 0.0e0
     555            0 :          v1hspinfield(2*ifft-1,2)  = 0.5e0
     556            0 :          v1hspinfield(2*ifft  ,2)  = 0.0e0
     557              :        end do
     558              :      end if
     559           58 :    else if (nspden==4) then
     560           58 :      select case(idir)
     561              :      case(1) !along x, v1=-sigma_x
     562       177685 :        do ifft=1,nfft
     563       177664 :          v1hspinfield(2*ifft-1,1)= 0.0e0 !Re[V^11]
     564       177664 :          v1hspinfield(2*ifft  ,1)= 0.0e0 !Im[V^11]
     565       177664 :          v1hspinfield(2*ifft-1,2)= 0.0e0 !Re[V^22]
     566       177664 :          v1hspinfield(2*ifft  ,2)= 0.0e0 !Im[V^22]
     567       177664 :          v1hspinfield(2*ifft-1,3)=-0.5e0 !Re[V^12]
     568       177664 :          v1hspinfield(2*ifft  ,3)= 0.0e0 !Im[V^12]
     569       177664 :          v1hspinfield(2*ifft-1,4)= 0.0e0 !Re[i.V^21]=Im[V^12]
     570       177685 :          v1hspinfield(2*ifft  ,4)=-0.5e0 !Im[i.V^21]=Re[V^12]
     571              :        end do
     572              :      case(2) !along y, v1 = -sigma_y
     573       152075 :        do ifft=1,nfft
     574       152064 :          v1hspinfield(2*ifft-1,1)= 0.0e0 !Re[V^11]
     575       152064 :          v1hspinfield(2*ifft  ,1)= 0.0e0 !Im[V^11]
     576       152064 :          v1hspinfield(2*ifft-1,2)= 0.0e0 !Re[V^22]
     577       152064 :          v1hspinfield(2*ifft  ,2)= 0.0e0 !Im[V^22]
     578       152064 :          v1hspinfield(2*ifft-1,3)= 0.0e0 !Re[V^12]
     579       152064 :          v1hspinfield(2*ifft  ,3)=+0.5e0 !Im[V^12]
     580       152064 :          v1hspinfield(2*ifft-1,4)=+0.5e0 !Re[i.V^21]=Im[V^12]
     581       152075 :          v1hspinfield(2*ifft  ,4)= 0.0e0 !Im[i.V^21]=Re[V^12]
     582              :        end do
     583              :      case(3)
     584       207375 :        do ifft=1,nfft
     585       207360 :          v1hspinfield(2*ifft-1,1)=-0.5e0 !Re[V^11]
     586       207360 :          v1hspinfield(2*ifft  ,1)= 0.0e0 !Im[V^11]
     587       207360 :          v1hspinfield(2*ifft-1,2)= 0.5e0 !Re[V^22]
     588       207360 :          v1hspinfield(2*ifft  ,2)= 0.0e0 !Im[V^22]
     589       207360 :          v1hspinfield(2*ifft-1,3)= 0.0e0 !Re[V^12]
     590       207360 :          v1hspinfield(2*ifft  ,3)= 0.0e0 !Im[V^12]
     591       207360 :          v1hspinfield(2*ifft-1,4)= 0.0e0 !Re[i.V^21]
     592       207375 :          v1hspinfield(2*ifft  ,4)= 0.0e0 !Im[i.V^21]
     593              :        end do
     594              :      case(4)
     595        33861 :        do ifft=1,nfft
     596        33792 :          v1hspinfield(2*ifft-1,1)=-0.5e0 !Re[V^11]
     597        33792 :          v1hspinfield(2*ifft  ,1)= 0.0e0 !Im[V^11]
     598        33792 :          v1hspinfield(2*ifft-1,2)=-0.5e0 !Re[V^22]
     599        33792 :          v1hspinfield(2*ifft  ,2)= 0.0e0 !Im[V^22]
     600        33792 :          v1hspinfield(2*ifft-1,3)= 0.0e0 !Re[V^12]
     601        33792 :          v1hspinfield(2*ifft  ,3)= 0.0e0 !Im[V^12]
     602        33792 :          v1hspinfield(2*ifft-1,4)= 0.0e0 !Re[i.V^21]
     603        33803 :          v1hspinfield(2*ifft  ,4)= 0.0e0 !Im[i.V^21]
     604              :        end do
     605              :      end select
     606              :    end if
     607              :  end select !cplex
     608              : 
     609           82 : end subroutine dfpt_v1hspinfield
     610              : !!***
     611              : 
     612              : !!****f* ABINIT/dfpt_v1magpen
     613              : !! NAME
     614              : !!  dfpt_v1magpen
     615              : !!
     616              : !! FUNCTION
     617              : !!  Calculate a 1st order penalty potential and energy in order to
     618              : !!  harden the spin degrees of freedom.
     619              : !!
     620              : !! INPUTS
     621              : !!  cplex  = complex or real density matrix
     622              : !!  magpen=energy shift to apply on the spin degrees of freedom
     623              : !!  mpatpol(2)=initial and final atomic positions whose local magnetic moments will be penalized
     624              : !!  mpdir(3)=directions of the magnetic moments to be penalized
     625              : !!  mpi_enreg=information about MPI parallelization
     626              : !!  nfft   = numbder of fft grid points
     627              : !!  ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft
     628              : !!  nspden = number of density matrix components
     629              : !!  qphon(3)=reduced coordinates for the phonon wavelength
     630              : !!  taumr(nfft,natom,3)= array describing r-xred(iatom) at any point of the FFT grid
     631              : !!  xred(3,natom)=reduced dimensionless atomic coordinates
     632              : !!
     633              : !! OUTPUT
     634              : !!  vmagpen1(nfft*cplex,nspden)= 1st order magnetic penalty potential
     635              : !!  emagpen1= magnetic penalty energy contribution to second-order energy
     636              : !!
     637              : !! SIDE EFFECTS
     638              : !!
     639              : !! NOTES
     640              : !!  The definition of components of the potential matrix differ depending on cplex:
     641              : !!  For cplex=1, the potential is defined as (V_upup,V_dndn,Re[V_updn],Im[V_updn])
     642              : !!  For cplex=2, the definition is (V_upup,V_dndn,V_updn,i.V_updn)
     643              : !!
     644              : !!  If magpen < 0 the penalty field is defined from the cell-integrated magnetic moments along the directions given by mpdir
     645              : !!  IF magpen > 0 the penalty field is defined from the atom spheres-integrated magnetic moments as given by mpatpol and mpdir
     646              : !!
     647              : !! SOURCE
     648              : 
     649           62 : subroutine dfpt_v1magpen(cplex,emagpen1,fatsph,intgden,magpen,mpatpol,mpdir,&
     650           62 : & natom,nfft,nspden,qphon,rhomag,taumr,vmagpen1)
     651              : 
     652              : !Arguments
     653              : !scalars:
     654              :  integer,intent(in)   :: cplex,natom,nfft,nspden
     655              :  real(dp),intent(in)  :: magpen
     656              :  real(dp),intent(out) :: emagpen1
     657              : !arrays:
     658              :  integer,intent(in)    :: mpatpol(2),mpdir(3)
     659              :  real(dp),intent(in)   :: fatsph(nfft,natom)
     660              :  real(dp),intent(in)   :: intgden(cplex,nspden,natom)
     661              :  real(dp), intent(in)  :: qphon(3)
     662              :  real(dp),intent(in)   :: rhomag(2,nspden)
     663              :  real(dp), intent(in)   :: taumr(nfft,natom,3)
     664              :  real(dp),intent(out)  :: vmagpen1(cplex*nfft,nspden)
     665              : 
     666              : !Local variables-------------------------------
     667              : !scalars:
     668              :  integer :: i,iatom,ifft,im,re
     669              :  real(dp) :: arg
     670              :  real(dp) :: phr1d_re,phr1d_im
     671              :  real(dp) :: Blocx_re,Blocy_re,Blocz_re
     672              :  real(dp) :: Blocx_im,Blocy_im,Blocz_im
     673              : !arrays:
     674          124 :  real(dp) :: Bx(cplex),By(cplex),Bz(cplex)
     675          124 :  real(dp) :: Blocx(cplex*nfft),Blocy(cplex*nfft),Blocz(cplex*nfft)
     676           62 :  real(dp) :: rhomag_eff(2,nspden),intgden_eff(cplex,nspden,natom)
     677              : 
     678              : ! *************************************************************************
     679              : 
     680          176 :  if (cplex==1.and.any(abs(qphon(:))>tol8)) then
     681            0 :    ABI_ERROR('Local Zeeman fields are cplex==2 at finite q vector')
     682              :  end if
     683              : 
     684              : !Compute magnetic penalty from cell-integrated magnetic moments
     685           62 :  if (magpen < zero) then
     686              : 
     687            0 :    rhomag_eff(:,1)=rhomag(:,1)
     688            0 :    rhomag_eff(:,2:4)=half*rhomag(:,2:4) !Convert from mu_B to a.u.
     689            0 :    do i=1,3
     690            0 :      if (mpdir(i)==0) rhomag_eff(:,1+i) = zero
     691              :    end do
     692              : 
     693            0 :    if (cplex==1) then
     694            0 :      emagpen1=-one*magpen*(rhomag_eff(1,2)**2+rhomag_eff(1,3)**2+rhomag_eff(1,4)**2)
     695            0 :    else if (cplex==2) then
     696              :      emagpen1=-one*magpen*(rhomag_eff(1,2)**2+rhomag_eff(2,2)**2 &
     697              :                         & + rhomag_eff(1,3)**2+rhomag_eff(2,3)**2 &
     698            0 :                         & + rhomag_eff(1,4)**2+rhomag_eff(2,4)**2 )
     699              :    end if
     700              : 
     701            0 :    Bx(:)=-half*magpen*rhomag_eff(:,2)
     702            0 :    By(:)=-half*magpen*rhomag_eff(:,3)
     703            0 :    Bz(:)=-half*magpen*rhomag_eff(:,4)
     704            0 :    if (cplex==1) then
     705            0 :      do ifft=1,nfft
     706            0 :        vmagpen1(ifft,1)=Bz(1)
     707            0 :        vmagpen1(ifft,2)=-Bz(1)
     708            0 :        vmagpen1(ifft,3)=Bx(1)
     709            0 :        vmagpen1(ifft,4)=-By(1)
     710              :      end do
     711            0 :    else if (cplex==2) then
     712            0 :      do ifft=1,nfft
     713            0 :        vmagpen1(2*ifft-1,1)=Bz(1)
     714            0 :        vmagpen1(2*ifft  ,1)=Bz(2)
     715            0 :        vmagpen1(2*ifft-1,2)=-Bz(1)
     716            0 :        vmagpen1(2*ifft  ,2)=-Bz(2)
     717            0 :        vmagpen1(2*ifft-1,3)=Bx(1)+By(2)
     718            0 :        vmagpen1(2*ifft  ,3)=Bx(2)-By(1)
     719            0 :        vmagpen1(2*ifft-1,4)=-Bx(2)-By(1)
     720            0 :        vmagpen1(2*ifft  ,4)=Bx(1)-By(2)
     721              :      end do
     722              :    end if
     723              : 
     724              : !Compute magnetic penalty from atom shperes-integrated magnetic moments
     725           62 :  else if (magpen > zero) then
     726           62 :    emagpen1=zero
     727       268862 :    Blocx=zero
     728       268862 :    Blocy=zero
     729       268862 :    Blocz=zero
     730              : 
     731         1064 :    intgden_eff(:,1,:)=intgden(:,1,:)
     732         3440 :    intgden_eff(:,2:4,:)=half*intgden(:,2:4,:) !Convert from mu_B to a.u.
     733          186 :    do iatom=mpatpol(1),mpatpol(2)
     734              : 
     735          496 :      do i=1,3
     736          706 :        if (mpdir(i)==0) intgden_eff(:,1+i,iatom) = zero
     737              :      end do
     738              : 
     739          124 :      if (cplex==1) then
     740              :        emagpen1=emagpen1+one*magpen*(intgden_eff(1,2,iatom)**2+ &
     741              :                                     & intgden_eff(1,3,iatom)**2+ &
     742           38 :                                     & intgden_eff(1,4,iatom)**2)
     743           86 :      else if (cplex==2) then
     744              :        emagpen1=emagpen1+one*magpen*(intgden_eff(1,2,iatom)**2+intgden_eff(2,2,iatom)**2 &
     745              :                           & + intgden_eff(1,3,iatom)**2+intgden_eff(2,3,iatom)**2 &
     746           86 :                           & + intgden_eff(1,4,iatom)**2+intgden_eff(2,4,iatom)**2 )
     747              :      end if
     748              : 
     749          186 :      if (cplex==1) then
     750        97318 :        do ifft=1,nfft
     751        97280 :          Blocx(ifft)=Blocx(ifft)+half*magpen*intgden_eff(1,2,iatom)*fatsph(ifft,iatom)
     752        97280 :          Blocy(ifft)=Blocy(ifft)+half*magpen*intgden_eff(1,3,iatom)*fatsph(ifft,iatom)
     753        97318 :          Blocz(ifft)=Blocz(ifft)+half*magpen*intgden_eff(1,4,iatom)*fatsph(ifft,iatom)
     754              :        end do
     755          344 :      else if (cplex==2.and.sum(qphon(:)**2) < tol8) then
     756        97318 :        do ifft=1,nfft
     757        97280 :          Blocx(2*ifft-1)=Blocx(2*ifft-1)+half*magpen*intgden_eff(1,2,iatom)*fatsph(ifft,iatom)
     758        97280 :          Blocy(2*ifft-1)=Blocy(2*ifft-1)+half*magpen*intgden_eff(1,3,iatom)*fatsph(ifft,iatom)
     759        97280 :          Blocz(2*ifft-1)=Blocz(2*ifft-1)+half*magpen*intgden_eff(1,4,iatom)*fatsph(ifft,iatom)
     760        97280 :          Blocx(2*ifft)=Blocx(2*ifft)+half*magpen*intgden_eff(2,2,iatom)*fatsph(ifft,iatom)
     761        97280 :          Blocy(2*ifft)=Blocy(2*ifft)+half*magpen*intgden_eff(2,3,iatom)*fatsph(ifft,iatom)
     762        97318 :          Blocz(2*ifft)=Blocz(2*ifft)+half*magpen*intgden_eff(2,4,iatom)*fatsph(ifft,iatom)
     763              :        end do
     764          192 :      else if (cplex==2.and.sum(qphon(:)**2) > tol8) then
     765       122928 :        do ifft=1,nfft
     766       122880 :          re=2*ifft-1
     767       122880 :          im=2*ifft
     768              : 
     769       122880 :          Blocx_re=+half*magpen*intgden_eff(1,2,iatom)*fatsph(ifft,iatom)
     770       122880 :          Blocy_re=+half*magpen*intgden_eff(1,3,iatom)*fatsph(ifft,iatom)
     771       122880 :          Blocz_re=+half*magpen*intgden_eff(1,4,iatom)*fatsph(ifft,iatom)
     772       122880 :          Blocx_im=+half*magpen*intgden_eff(2,2,iatom)*fatsph(ifft,iatom)
     773       122880 :          Blocy_im=+half*magpen*intgden_eff(2,3,iatom)*fatsph(ifft,iatom)
     774       122880 :          Blocz_im=+half*magpen*intgden_eff(2,4,iatom)*fatsph(ifft,iatom)
     775              : 
     776       491520 :          arg=two_pi*dot_product(qphon,-taumr(ifft,iatom,:))
     777       122880 :          phr1d_re=dcos(arg)
     778       122880 :          phr1d_im=dsin(arg)
     779              : 
     780       122880 :          Blocx(re)= Blocx(re)+phr1d_re*Blocx_re-phr1d_im*Blocx_im
     781       122880 :          Blocx(im)= Blocx(im)+phr1d_im*Blocx_re+phr1d_re*Blocx_im
     782       122880 :          Blocy(re)= Blocy(re)+phr1d_re*Blocy_re-phr1d_im*Blocy_im
     783       122880 :          Blocy(im)= Blocy(im)+phr1d_im*Blocy_re+phr1d_re*Blocy_im
     784       122880 :          Blocz(re)= Blocz(re)+phr1d_re*Blocz_re-phr1d_im*Blocz_im
     785       122928 :          Blocz(im)= Blocz(im)+phr1d_im*Blocz_re+phr1d_re*Blocz_im
     786              :        end do
     787              :      end if
     788              : 
     789              :    end do  !iatom
     790              : 
     791           62 :    if (cplex==1) then
     792        48659 :      do ifft=1,nfft
     793        48640 :        vmagpen1(ifft,1)=Blocz(ifft)
     794        48640 :        vmagpen1(ifft,2)=-Blocz(ifft)
     795        48640 :        vmagpen1(ifft,3)=Blocx(ifft)
     796        48659 :        vmagpen1(ifft,4)=-Blocy(ifft)
     797              :      end do
     798           43 :    else if (cplex==2) then
     799       110123 :      do ifft=1,nfft
     800       110080 :        vmagpen1(2*ifft-1,1)=Blocz(2*ifft-1)
     801       110080 :        vmagpen1(2*ifft  ,1)=Blocz(2*ifft)
     802       110080 :        vmagpen1(2*ifft-1,2)=-Blocz(2*ifft-1)
     803       110080 :        vmagpen1(2*ifft  ,2)=-Blocz(2*ifft)
     804       110080 :        vmagpen1(2*ifft-1,3)=Blocx(2*ifft-1)+Blocy(2*ifft)
     805       110080 :        vmagpen1(2*ifft  ,3)=Blocx(2*ifft)-Blocy(2*ifft-1)
     806       110080 :        vmagpen1(2*ifft-1,4)=-Blocx(2*ifft)-Blocy(2*ifft-1)
     807       110123 :        vmagpen1(2*ifft  ,4)=Blocx(2*ifft-1)-Blocy(2*ifft)
     808              :      end do
     809              :    end if
     810              : 
     811              :  end if
     812              : 
     813           62 : end subroutine dfpt_v1magpen
     814              : !!***
     815              : 
     816              : !!****f* ABINIT/dfpt_v1hspinfield_atsph
     817              : !! NAME
     818              : !!  dfpt_v1hspinfield_atsph
     819              : !!
     820              : !! FUNCTION
     821              : !!  Calculate 1st order potential due to a local Zeeman field inside an
     822              : !!  atom centered sphere= -vec{\sigma}.\vec{b}*f_i(r), where
     823              : !!  sigma is the vector of Pauli matrices, \vec{b}(r) is the unit
     824              : !!  vector indicating the perturbing field direction and f_i(r) is the
     825              : !!  real-space function defining the sphere around atom i.
     826              : !!
     827              : !! INPUTS
     828              : !!  nspden = number of density matrix components
     829              : !!  nfft   = numbder of fft grid points
     830              : !!  ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft
     831              : !!  cplex  = complex or real density matrix
     832              : !!  fatsph(nfft,natom)= functions defining the atomic spheres of integration in real space
     833              : !!  idir   = direction of the perturbing field in Cartesian frame
     834              : !!           1: along x
     835              : !!           2: along y
     836              : !!           3: along z
     837              : !!           4: identity matrix at each fft point is returned (for density-density response)
     838              : !!  qphon(3)=reduced coordinates for the phonon wavelength
     839              : !!  taumr(nfft,natom,3)= array describing r-xred(iatom) at any point of the FFT grid
     840              : !!  xred(3,natom)=reduced dimensionless atomic coordinates
     841              : !!
     842              : !! OUTPUT
     843              : !!  v1hspinfield(nfft*cplex,nspden)= 1st order Zeeman potential, or Identity matrix (electrostatic potential) for idir=4
     844              : !!
     845              : !! SIDE EFFECTS
     846              : !!
     847              : !! NOTES
     848              : !!  The definition of components of the potential matrix differ depending on cplex
     849              : !!  for nspden=4:
     850              : !!  For cplex=1, the potential is defined as (V_upup,V_dndn,Re[V_updn],Im[V_updn])
     851              : !!  For cplex=2, the definition is (V_upup,V_dndn,V_updn,i.V_updn)
     852              : !!
     853              : !! SOURCE
     854              : 
     855           17 : subroutine dfpt_v1hspinfield_atsph(cplex,fatsph,idir,ipert,natom,nfft,nspden,&
     856           17 : & qphon,taumr,v1hspinfield)
     857              : 
     858              : !Arguments ------------------------------------
     859              : !scalars
     860              :  integer, intent(in)    :: idir,ipert,nfft,cplex,natom,nspden
     861              : !arrays
     862              :  real(dp), intent(in)   :: fatsph(nfft,natom)
     863              :  real(dp), intent(in)   :: qphon(3)
     864              :  real(dp), intent(inout):: v1hspinfield(cplex*nfft,nspden)
     865              :  real(dp), intent(in)   :: taumr(nfft,natom,3)
     866              : 
     867              : !Local variables-------------------------------
     868              : !scalars
     869              :  integer :: ifft,iatom,im,re
     870              :  real(dp) :: arg
     871              :  real(dp) :: phr1d_re,phr1d_im
     872              :  real(dp) :: Bloc_re, Bloc_im
     873              :  character(len=500) :: msg
     874              : !arrays
     875           17 :  real(dp) :: Bloc(cplex*nfft)
     876              : 
     877              : ! *************************************************************************
     878              : 
     879           47 :  if (cplex==1.and.any(abs(qphon(:))>tol8)) then
     880            0 :    ABI_ERROR('Local Zeeman fields are cplex==2 at finite q vector')
     881              :  end if
     882              : 
     883           17 :  iatom=ipert-natom-11
     884              : 
     885              :  !Define the local magnetic field
     886           17 :  if (cplex==1) then
     887        12805 :    do ifft=1,nfft
     888        12805 :      Bloc(ifft)=-half*fatsph(ifft,iatom)
     889              :    end do
     890           12 :  else if (cplex==2) then
     891        30732 :    do ifft=1,nfft
     892        30720 :      re=2*ifft-1
     893        30720 :      im=2*ifft
     894       122892 :      if (sum(qphon(:)**2)<tol8) then
     895        12800 :        Bloc(re)=-half*fatsph(ifft,iatom)
     896        12800 :        Bloc(im)=zero
     897              :      else
     898        17920 :        Bloc_re=-half*fatsph(ifft,iatom)
     899        17920 :        Bloc_im=zero
     900        71680 :        arg=two_pi*dot_product(qphon,-taumr(ifft,iatom,:))
     901        17920 :        phr1d_re=dcos(arg)
     902        17920 :        phr1d_im=dsin(arg)
     903        17920 :        Bloc(re)=phr1d_re*Bloc_re-phr1d_im*Bloc_im
     904        17920 :        Bloc(im)=phr1d_im*Bloc_re+phr1d_re*Bloc_im
     905              :      end if
     906              :    end do
     907              :  end if
     908              : 
     909              :  !Build the first-order potential
     910            5 :  select case(cplex)
     911              :  case(1)
     912            5 :    if (nspden==4) then
     913            5 :      if(idir==3)then       ! Zeeman field along the 3rd axis (z)
     914            0 :        do ifft=1,nfft
     915            0 :          v1hspinfield(ifft,1)=Bloc(ifft)
     916            0 :          v1hspinfield(ifft,2)=-Bloc(ifft)
     917            0 :          v1hspinfield(ifft,3)= 0.0d0
     918            0 :          v1hspinfield(ifft,4)= 0.0d0
     919              :        end do
     920            5 :      else if(idir==2)then  ! Zeeman field along the 2nd axis (y)
     921            0 :        do ifft=1,nfft
     922            0 :          v1hspinfield(ifft,1)= 0.0d0
     923            0 :          v1hspinfield(ifft,2)= 0.0d0
     924            0 :          v1hspinfield(ifft,3)= 0.0d0
     925            0 :          v1hspinfield(ifft,4)=-Bloc(ifft)
     926              :        end do
     927              :      else                  ! Zeeman field along the 1st axis (x)
     928        12805 :        do ifft=1,nfft
     929        12800 :          v1hspinfield(ifft,1)= 0.0d0
     930        12800 :          v1hspinfield(ifft,2)= 0.0d0
     931        12800 :          v1hspinfield(ifft,3)=Bloc(ifft)
     932        12805 :          v1hspinfield(ifft,4)= 0.0d0
     933              :        end do
     934              :      end if
     935              :    else
     936            0 :      write(msg,*) 'Response to local Zeeman fields only implemented for nspden=4'
     937            0 :      ABI_BUG(msg)
     938              :    end if
     939              :  case(2)
     940           17 :    if (nspden==4) then
     941           12 :      select case(idir)
     942              :      case(1) !along x, v1=-sigma_x
     943        30732 :        do ifft=1,nfft
     944        30720 :          v1hspinfield(2*ifft-1,1)= 0.0e0 !Re[V^11]
     945        30720 :          v1hspinfield(2*ifft  ,1)= 0.0e0 !Im[V^11]
     946        30720 :          v1hspinfield(2*ifft-1,2)= 0.0e0 !Re[V^22]
     947        30720 :          v1hspinfield(2*ifft  ,2)= 0.0e0 !Im[V^22]
     948        30720 :          v1hspinfield(2*ifft-1,3)= Bloc(2*ifft-1) !Re[V^12]
     949        30720 :          v1hspinfield(2*ifft  ,3)= Bloc(2*ifft) !Im[V^12]
     950        30720 :          v1hspinfield(2*ifft-1,4)=-Bloc(2*ifft) !Re[i.V^21]=Im[V^12]
     951        30732 :          v1hspinfield(2*ifft  ,4)= Bloc(2*ifft-1) !Im[i.V^21]=Re[V^12]
     952              :        end do
     953              :      case(2) !along y, v1 = -sigma_y
     954            0 :        do ifft=1,nfft
     955            0 :          v1hspinfield(2*ifft-1,1)= 0.0e0 !Re[V^11]
     956            0 :          v1hspinfield(2*ifft  ,1)= 0.0e0 !Im[V^11]
     957            0 :          v1hspinfield(2*ifft-1,2)= 0.0e0 !Re[V^22]
     958            0 :          v1hspinfield(2*ifft  ,2)= 0.0e0 !Im[V^22]
     959            0 :          v1hspinfield(2*ifft-1,3)= Bloc(2*ifft)  !Re[V^12]
     960            0 :          v1hspinfield(2*ifft  ,3)=-Bloc(2*ifft-1) !Im[V^12]
     961            0 :          v1hspinfield(2*ifft-1,4)=-Bloc(2*ifft-1) !Re[i.V^21]=Im[V^12]
     962            0 :          v1hspinfield(2*ifft  ,4)=-Bloc(2*ifft) !Im[i.V^21]=Re[V^12]
     963              :        end do
     964              :      case(3)
     965           12 :        do ifft=1,nfft
     966            0 :          v1hspinfield(2*ifft-1,1)= Bloc(2*ifft-1) !Re[V^11]
     967            0 :          v1hspinfield(2*ifft  ,1)= Bloc(2*ifft)   !Im[V^11]
     968            0 :          v1hspinfield(2*ifft-1,2)=-Bloc(2*ifft-1) !Re[V^22]
     969            0 :          v1hspinfield(2*ifft  ,2)=-Bloc(2*ifft)  !Im[V^22]
     970            0 :          v1hspinfield(2*ifft-1,3)= 0.0e0 !Re[V^12]
     971            0 :          v1hspinfield(2*ifft  ,3)= 0.0e0 !Im[V^12]
     972            0 :          v1hspinfield(2*ifft-1,4)= 0.0e0 !Re[i.V^21]
     973            0 :          v1hspinfield(2*ifft  ,4)= 0.0e0 !Im[i.V^21]
     974              :        end do
     975              :      end select
     976              :    else
     977            0 :      write(msg,*) 'Response to local spin fields only implemented for nspden=4'
     978            0 :      ABI_BUG(msg)
     979              :    end if
     980              :  end select !cplex
     981              : 
     982           17 : end subroutine dfpt_v1hspinfield_atsph
     983              : !!***
     984              : 
     985              : end module m_dfpt_rhotov
     986              : !!***
        

Generated by: LCOV version 2.3-1