TABLE OF CONTENTS


ABINIT/m_paw_optics [ Modules ]

[ Top ] [ Modules ]

NAME

  m_paw_optics

FUNCTION

  This module contains several routines related to conductivity:
    optical conductivity, X spectroscopy, linear susceptibility, ...

COPYRIGHT

 Copyright (C) 2018-2024 ABINIT group (SM,VR,FJ,MT,NB,PGhosh)
 This file is distributed under the terms of the
 GNU General Public License, see ~abinit/COPYING
 or http://www.gnu.org/copyleft/gpl.txt .

SOURCE

17 #if defined HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20 
21 #include "abi_common.h"
22 
23 MODULE m_paw_optics
24 
25  use defs_basis
26  use m_xmpi
27  use m_errors
28  use m_wffile
29  use m_abicore
30  use m_hdr
31  use m_dtset
32  use m_dtfil
33  use m_nctk
34 #ifdef HAVE_NETCDF
35  use netcdf
36 #endif
37 
38  use defs_datatypes, only : pseudopotential_type
39  use defs_abitypes,  only : MPI_type
40  use m_time,         only : timab
41  use m_io_tools,     only : open_file,get_unit,close_unit
42  use m_pawpsp,       only : pawpsp_read_corewf
43  use m_pawrad,       only : pawrad_type,pawrad_deducer0,simp_gen,nderiv_gen,poisson
44  use m_pawtab,       only : pawtab_type
45  use m_pawcprj,      only : pawcprj_type,pawcprj_alloc,pawcprj_get, &
46 &                           pawcprj_free,pawcprj_mpi_allgather
47  use m_pawang,       only : pawang_type
48  use m_paw_denpot,   only : pawdensities,pawkindensities,pawdenpot
49  use m_paw_an,       only : paw_an_type,paw_an_init,paw_an_free,paw_an_copy
50  use m_pawrhoij,     only : pawrhoij_type
51  use m_paw_ij,       only : paw_ij_type
52  use m_paw_onsite,   only : pawnabla_init,pawnabla_core_init
53  use m_paw_sphharm,  only : setnabla_ylm
54  use m_pawxc,        only : pawxc,pawxcm,pawxc_get_xclevel,pawxc_get_usekden
55  use m_mpinfo,       only : destroy_mpi_enreg,nullify_mpi_enreg,initmpi_seq,proc_distrb_cycle
56  use m_numeric_tools,only : kramerskronig
57  use m_geometry,     only : metric
58  use m_hide_lapack,  only : matrginv
59  use m_paral_atom,   only : get_my_atmtab,free_my_atmtab
60 
61  implicit none
62 
63  private
64 
65 !public procedures.
66  public :: optics_paw
67  public :: optics_paw_core
68  public :: linear_optics_paw
69 
70 !I/O parameters
71 !Set to true to force the use of netCDF when available
72 ! overriding the value of dtset%iomode
73  logical,parameter :: use_netcdf_forced=.true.
74 !Set to true to use netcdf-MPIIO when available
75  logical,parameter :: use_netcdf_mpiio=.true.
76 !Set to true to compute/write only half of the (n,m) dipoles
77  logical,parameter :: compute_half_dipoles=.true.
78 !Set to true to use unlimited dimensions in netCDF file (experimental)
79 !  This is not mandatory because we know exactly the amount of data to write
80 !    and seems to impact performances negatively...
81 !    Not compatible with compute_half_dipoles=.true.
82  logical,parameter :: use_netcdf_unlimited=.false.
83 
84 CONTAINS  !========================================================================================

m_paw_optics/linear_optics_paw [ Functions ]

[ Top ] [ m_paw_optics ] [ Functions ]

NAME

 linear_optics_paw

FUNCTION

 This program computes the elements of the optical frequency dependent
 linear susceptiblity using matrix elements <-i Nabla> obtained from a
 PAW ground state calculation. It uses formula 17 from Gadoc et al,
 Phys. Rev. B 73, 045112 (2006) [[cite:Gajdo2006]] together with a scissors correction. It uses
 a Kramers-Kronig transform to compute the real part from the imaginary part, and
 it will work on all types of unit cells. It outputs all tensor elements of
 both the real and imaginary parts.

INPUTS

  filnam: base of file names to read data from
  mpi_enreg: mpi set up variable, not used in this code

OUTPUT

  _real and _imag output files

NOTES

  This routine is not tested

SOURCE

1507  subroutine linear_optics_paw(filnam,filnam_out)
1508 
1509 !Arguments -----------------------------------
1510 !scalars
1511  character(len=fnlen),intent(in) :: filnam,filnam_out
1512 
1513 !Local variables-------------------------------
1514  integer,parameter :: master=0
1515  integer :: iomode,bantot,bdtot_index,fform1,headform
1516  integer :: iband,ierr,ii,ikpt,iom,iout,isppol,isym,jband,jj,me,mband
1517  integer :: method,mom,nband_k,nkpt,nspinor,nsppol,nsym,occopt,only_check
1518  integer :: rdwr,spaceComm,inpunt,reunt,imunt,wfunt
1519  integer,allocatable :: nband(:),symrel(:,:,:)
1520  real(dp) :: del,dom,fij,gdelta,omin,omax,paijpbij(2),mbpt_sciss,wij,ucvol
1521  real(dp) :: diffwp, diffwm
1522  real(dp) :: e2rot(3,3),gmet(3,3),gprimd(3,3),rmet(3,3),rprimd(3,3),rprimdinv(3,3),symd(3,3),symdinv(3,3)
1523  real(dp),allocatable :: e1(:,:,:),e2(:,:,:,:),epsilon_tot(:,:,:,:),eigen0(:),eig0_k(:)
1524  real(dp),allocatable :: kpts(:,:),occ(:),occ_k(:),oml1(:),wtk(:)
1525  complex(dpc),allocatable :: eps_work(:)
1526  character(len=fnlen) :: filnam1,filnam_gen
1527  character(len=500) :: msg
1528  type(hdr_type) :: hdr
1529  type(wffile_type) :: wff1
1530 !arrays
1531  real(dp),allocatable :: psinablapsi(:,:,:,:)
1532 
1533 ! *********************************************************************************
1534 
1535  DBG_ENTER("COLL")
1536 
1537 !write(std_out,'(a)')' Give the name of the output file ...'
1538 !read(std_in, '(a)') filnam_out
1539 !write(std_out,'(a)')' The name of the output file is :',filnam_out
1540 
1541 !Read data file
1542  if (open_file(filnam,msg,newunit=inpunt,form='formatted') /= 0 ) then
1543    ABI_ERROR(msg)
1544  end if
1545 
1546  rewind(inpunt)
1547  read(inpunt,*)
1548  read(inpunt,'(a)')filnam_gen       ! generic name for the files
1549  filnam1=trim(filnam_gen)//'_OPT' ! nabla matrix elements file
1550 
1551 !Open the Wavefunction and optic files
1552 !These default values are typical of sequential use
1553  iomode=IO_MODE_FORTRAN ; spaceComm=xmpi_comm_self; me=0
1554 
1555 ! Read the header of the optic files
1556  call hdr_read_from_fname(hdr, filnam1, fform1, spaceComm)
1557  call hdr%free()
1558  if (fform1 /= 610) then
1559    ABI_ERROR("Abinit8 requires an OPT file with fform = 610")
1560  end if
1561 
1562 !Open the conducti optic files
1563  wfunt = get_unit()
1564  call WffOpen(iomode,spaceComm,filnam1,ierr,wff1,master,me,wfunt)
1565 
1566 !Read the header from Ground state file
1567  rdwr=1
1568  call hdr_io(fform1,hdr,rdwr,wff1)
1569 
1570 !Extract info from the header
1571  headform=hdr%headform
1572  bantot=hdr%bantot
1573  nkpt=hdr%nkpt
1574  ABI_MALLOC(kpts,(3,nkpt))
1575  ABI_MALLOC(wtk,(nkpt))
1576  kpts(:,:)=hdr%kptns(:,:)
1577  wtk(:)=hdr%wtk(:)
1578  nspinor=hdr%nspinor
1579  nsppol=hdr%nsppol
1580  occopt=hdr%occopt
1581  rprimd(:,:)=hdr%rprimd(:,:)
1582  rprimdinv(:,:) = rprimd(:,:)
1583  call matrginv(rprimdinv,3,3) ! need the inverse of rprimd to symmetrize the tensors
1584  ABI_MALLOC(nband,(nkpt*nsppol))
1585  ABI_MALLOC(occ,(bantot))
1586  occ(1:bantot)=hdr%occ(1:bantot)
1587  nband(1:nkpt*nsppol)=hdr%nband(1:nkpt*nsppol)
1588  nsym=hdr%nsym
1589  ABI_MALLOC(symrel,(3,3,nsym))
1590  symrel(:,:,:)=hdr%symrel(:,:,:)
1591 
1592 !Get mband, as the maximum value of nband(nkpt)
1593  mband=maxval(nband(:))
1594 
1595 !get ucvol etc.
1596  iout = -1
1597  call metric(gmet,gprimd,iout,rmet,rprimd,ucvol)
1598 
1599  write(std_out,*)
1600  write(std_out,'(a,3f10.5,a)' )' rprimd(bohr)      =',rprimd(1:3,1)
1601  write(std_out,'(a,3f10.5,a)' )'                    ',rprimd(1:3,2)
1602  write(std_out,'(a,3f10.5,a)' )'                    ',rprimd(1:3,3)
1603  write(std_out,*)
1604  write(std_out,'(a,3f10.5,a)' )' rprimdinv         =',rprimdinv(1:3,1)
1605  write(std_out,'(a,3f10.5,a)' )'                    ',rprimdinv(1:3,2)
1606  write(std_out,'(a,3f10.5,a)' )'                    ',rprimdinv(1:3,3)
1607  write(std_out,'(a,2i8)')      ' nkpt,mband        =',nkpt,mband
1608 
1609 !get eigen0
1610  ABI_MALLOC(eigen0,(mband*nkpt*nsppol))
1611  read(wfunt)(eigen0(iband),iband=1,mband*nkpt*nsppol)
1612 
1613  read(inpunt,*)mbpt_sciss
1614  read(inpunt,*)dom,omin,omax,mom
1615  close(inpunt)
1616 
1617  ABI_MALLOC(oml1,(mom))
1618  ABI_MALLOC(e1,(3,3,mom))
1619  ABI_MALLOC(e2,(2,3,3,mom))
1620  ABI_MALLOC(epsilon_tot,(2,3,3,mom))
1621  ABI_MALLOC(eps_work,(mom))
1622  del=(omax-omin)/(mom-1)
1623  do iom=1,mom
1624    oml1(iom)=omin+dble(iom-1)*del
1625  end do
1626  write(std_out,'(a,i8,4f10.5,a)')' npts,omin,omax,width,mbpt_sciss      =',mom,omin,omax,dom,mbpt_sciss,' Ha'
1627 
1628  ABI_MALLOC(psinablapsi,(2,3,mband,mband))
1629 
1630 !loop over spin components
1631  do isppol=1,nsppol
1632    bdtot_index = 0
1633 !  loop over k points
1634    do ikpt=1,nkpt
1635 !
1636 !    number of bands for this k point
1637      nband_k=nband(ikpt+(isppol-1)*nkpt)
1638      ABI_MALLOC(eig0_k,(nband_k))
1639      ABI_MALLOC(occ_k,(nband_k))
1640 !    eigenvalues for this k-point
1641      eig0_k(:)=eigen0(1+bdtot_index:nband_k+bdtot_index)
1642 !    occupation numbers for this k-point
1643      occ_k(:)=occ(1+bdtot_index:nband_k+bdtot_index)
1644 !    values of -i*nabla matrix elements for this k point
1645      psinablapsi=zero
1646      read(wfunt)((psinablapsi(1:2,1,iband,jband),iband=1,nband_k),jband=1,nband_k)
1647      read(wfunt)((psinablapsi(1:2,2,iband,jband),iband=1,nband_k),jband=1,nband_k)
1648      read(wfunt)((psinablapsi(1:2,3,iband,jband),iband=1,nband_k),jband=1,nband_k)
1649 
1650 !    occupation numbers for k-point
1651      occ_k(:)=occ(1+bdtot_index:nband_k+bdtot_index)
1652 !    accumulate e2 for this k point, Eq. 17 from PRB 73, 045112 (2006) [[cite:Gajdo2006]]
1653      do iband = 1, nband_k
1654        do jband = 1, nband_k
1655          fij = occ_k(iband) - occ_k(jband) !occ number difference
1656          wij = eig0_k(iband) - eig0_k(jband) !energy difference
1657          if (abs(fij) > zero) then ! only consider states of differing occupation numbers
1658            do ii = 1, 3
1659              do jj = 1, 3
1660                paijpbij(1) = psinablapsi(1,ii,iband,jband)*psinablapsi(1,jj,iband,jband) + &
1661 &               psinablapsi(2,ii,iband,jband)*psinablapsi(2,jj,iband,jband)
1662                paijpbij(2) = psinablapsi(2,ii,iband,jband)*psinablapsi(1,jj,iband,jband) - &
1663 &               psinablapsi(1,ii,iband,jband)*psinablapsi(2,jj,iband,jband)
1664                do iom = 1, mom
1665 !                original version
1666 !                diffw = wij + mbpt_sciss - oml1(iom) ! apply scissors term here
1667 !                gdelta = exp(-diffw*diffw/(4.0*dom*dom))/(2.0*dom*sqrt(pi)) ! delta fnc resolved as Gaussian
1668 !                e2(1,ii,jj,iom) = e2(1,ii,jj,iom) - (4.0*pi*pi/ucvol)*wtk(ikpt)*fij*paijpbij(1)*gdelta/(oml1(iom)*oml1(iom))
1669 !                e2(2,ii,jj,iom) = e2(2,ii,jj,iom) - (4.0*pi*pi/ucvol)*wtk(ikpt)*fij*paijpbij(2)*gdelta/(oml1(iom)*oml1(iom))
1670                  diffwm = wij - mbpt_sciss + oml1(iom) ! apply scissors term here
1671                  diffwp = wij + mbpt_sciss - oml1(iom) ! apply scissors term here
1672                  gdelta = exp(-diffwp*diffwp/(4.0*dom*dom))/(2.0*dom*sqrt(pi))
1673                  e2(1,ii,jj,iom) = e2(1,ii,jj,iom) - (4.0*pi*pi/ucvol)*wtk(ikpt)*fij*paijpbij(1)*gdelta/(wij*wij)
1674                  e2(2,ii,jj,iom) = e2(2,ii,jj,iom) - (4.0*pi*pi/ucvol)*wtk(ikpt)*fij*paijpbij(2)*gdelta/(wij*wij)
1675                end do ! end loop over spectral points
1676              end do ! end loop over jj = 1, 3
1677            end do ! end loop over ii = 1, 3
1678          end if ! end selection on fij /= 0
1679        end do ! end loop over jband
1680      end do ! end loop over iband
1681 
1682      ABI_FREE(eig0_k)
1683      ABI_FREE(occ_k)
1684      bdtot_index=bdtot_index+nband_k
1685    end do ! end loop over k points
1686  end do ! end loop over spin polarizations
1687 
1688 !here apply nsym symrel transformations to reconstruct full tensor from IBZ part
1689  epsilon_tot(:,:,:,:) = zero
1690  do isym = 1, nsym
1691    symd(:,:)=matmul(rprimd(:,:),matmul(symrel(:,:,isym),rprimdinv(:,:)))
1692    symdinv(:,:)=symd(:,:)
1693    call matrginv(symdinv,3,3)
1694    do iom = 1, mom
1695      e2rot(:,:)=matmul(symdinv(:,:),matmul(e2(1,:,:,iom),symd(:,:)))
1696      epsilon_tot(2,:,:,iom) = epsilon_tot(2,:,:,iom)+e2rot(:,:)/nsym
1697    end do
1698  end do
1699 
1700 !generate e1 from e2 via KK transforma
1701  method=0 ! use naive integration ( = 1 for simpson)
1702  only_check=0 ! compute real part of eps in kk routine
1703  do ii = 1, 3
1704    do jj = 1, 3
1705      eps_work(:) = cmplx(0.0,epsilon_tot(2,ii,jj,:), kind=dpc)
1706      call kramerskronig(mom,oml1,eps_work,method,only_check)
1707      epsilon_tot(1,ii,jj,:) = real(eps_work(:))
1708      if (ii /= jj) epsilon_tot(1,ii,jj,:) = epsilon_tot(1,ii,jj,:)- 1.0
1709    end do ! end loop over jj
1710  end do ! end loop over ii
1711 
1712  if (open_file(trim(filnam_out)//'_imag',msg,newunit=reunt,form='formatted') /= 0) then
1713    ABI_ERROR(msg)
1714  end if
1715 
1716  if (open_file(trim(filnam_out)//'_real',msg,unit=imunt,form='formatted') /= 0) then
1717    ABI_ERROR(msg)
1718  end if
1719 
1720  write(reunt,'(a12,6a13)')' # Energy/Ha ','eps_2_xx','eps_2_yy','eps_2_zz',&
1721 & 'eps_2_yz','eps_2_xz','eps_2_xy'
1722  write(imunt,'(a12,6a13)')' # Energy/Ha ','eps_1_xx','eps_1_yy','eps_1_zz',&
1723 & 'eps_1_yz','eps_1_xz','eps_1_xy'
1724 
1725  do iom = 1, mom
1726    write(reunt,'(ES12.4,a,ES12.4,a,ES12.4,a,ES12.4,a,ES12.4,a,ES12.4,a,ES12.4)') oml1(iom),' ',&
1727 &   epsilon_tot(2,1,1,iom),' ',epsilon_tot(2,2,2,iom),' ',epsilon_tot(2,3,3,iom),' ',&
1728 &   epsilon_tot(2,2,3,iom),' ',epsilon_tot(2,1,3,iom),' ',epsilon_tot(2,1,2,iom)
1729    write(imunt,'(ES12.4,a,ES12.4,a,ES12.4,a,ES12.4,a,ES12.4,a,ES12.4,a,ES12.4)') oml1(iom),' ',&
1730 &   epsilon_tot(1,1,1,iom),' ',epsilon_tot(1,2,2,iom),' ',epsilon_tot(1,3,3,iom),' ',&
1731 &   epsilon_tot(1,2,3,iom),' ',epsilon_tot(1,1,3,iom),' ',epsilon_tot(1,1,2,iom)
1732  end do
1733 
1734  close(reunt)
1735  close(imunt)
1736 
1737  ABI_FREE(nband)
1738  ABI_FREE(oml1)
1739  ABI_FREE(e2)
1740  ABI_FREE(e1)
1741  ABI_FREE(occ)
1742  ABI_FREE(psinablapsi)
1743  ABI_FREE(eigen0)
1744  ABI_FREE(wtk)
1745  ABI_FREE(kpts)
1746 
1747  call hdr%free()
1748 
1749  DBG_EXIT("COLL")
1750 
1751  end subroutine linear_optics_paw

m_paw_optics/optics_paw [ Functions ]

[ Top ] [ m_paw_optics ] [ Functions ]

NAME

 optics_paw

FUNCTION

 Compute matrix elements need for optical conductivity (in the PAW context) and store them in a file
  Matrix elements = <Phi_i|Nabla|Phi_j>

INPUTS

  atindx1(natom)=index table for atoms, inverse of atindx (see gstate.f)
  cg(2,mcg)=planewave coefficients of wavefunctions.
  cprj(natom,mcprj)= <p_lmn|Cnk> coefficients for each WF |Cnk>
                                          and each |p_lmn> non-local projector
  dimcprj(natom)=array of dimensions of array cprj (not ordered)
  dtfil <type(datafiles_type)>=variables related to files
  dtset <type(dataset_type)>=all input variables for this dataset
  gprimd(3,3)=dimensional reciprocal space primitive translations
  kg(3,mpw*mkmem)=reduced planewave coordinates.
  mband=maximum number of bands
  mcg=size of wave-functions array (cg) =mpw*nspinor*mband*mkmem*nsppol
  mcprj=size of projected wave-functions array (cprj) =nspinor*mband*mkmem*nsppol
  mkmem =number of k points treated by this node.
  mpi_enreg=information about MPI parallelization
  mpsang =1+maximum angular momentum for nonlocal pseudopotentials
  mpw=maximum dimensioned size of npw.
  natom=number of atoms in cell.
  nkpt=number of k points.
  npwarr(nkpt)=number of planewaves in basis at this k point
  nsppol=1 for unpolarized, 2 for spin-polarized
  pawang <type(pawang_type)>= PAW ANGular mesh discretization and related data
  pawrad(ntypat) <type(pawrad_type)>=paw radial mesh and related data
  pawrhoij(my_natom) <type(pawrhoij_type)>= PAW rhoij occupancies and related data
  pawtab(ntypat) <type(pawtab_type)>=paw tabulated starting data
  znucl(ntypat)=atomic number of atom type

OUTPUT

  (only writing in a file)

SIDE EFFECTS

NOTES

SOURCE

133  subroutine optics_paw(atindx1,cg,cprj,dimcprj,dtfil,dtset,eigen0,gprimd,hdr,kg,&
134 &               mband,mcg,mcprj,mkmem,mpi_enreg,mpsang,mpw,natom,nkpt,npwarr,nsppol,&
135 &               pawang,pawrad,pawrhoij,pawtab,znucl)
136 
137 !Arguments ------------------------------------
138 !scalars
139  integer,intent(in) :: mband,mcg,mcprj,mkmem,mpsang,mpw,natom,nkpt,nsppol
140  type(MPI_type),intent(in) :: mpi_enreg
141  type(datafiles_type),intent(in) :: dtfil
142  type(dataset_type),intent(in) :: dtset
143  type(hdr_type),intent(inout) :: hdr
144  type(pawang_type),intent(in) :: pawang
145 !arrays
146  integer,intent(in) :: atindx1(natom),dimcprj(natom),npwarr(nkpt)
147  integer,intent(in),target :: kg(3,mpw*mkmem)
148  real(dp),intent(in) :: eigen0(mband*nkpt*nsppol)
149  real(dp),intent(in) :: gprimd(3,3),znucl(dtset%ntypat)
150  real(dp),intent(inout) :: cg(2,mcg)
151  type(pawcprj_type),target,intent(inout) :: cprj(natom,mcprj)
152  type(pawrad_type),intent(in) :: pawrad(dtset%ntypat)
153  type(pawrhoij_type),intent(inout) :: pawrhoij(mpi_enreg%my_natom)
154  type(pawtab_type),target,intent(inout) :: pawtab(dtset%ntypat)
155 
156 !Local variables-------------------------------
157 !scalars
158  integer,parameter :: master=0
159  integer :: bsize,iomode,bdtot_index,cplex,etiq,fformopt,iatom,ib,ibmax,ibg,ibsp
160  integer :: ibshift,icg,ierr,ikg,ikpt,ilmn,ount,ncid,varid,idir
161  integer :: iorder_cprj,ipw,ispinor,isppol,istwf_k,itypat,iwavef
162  integer :: jb,jbshift,jbsp,my_jb,jlmn,jwavef,lmn_size,mband_cprj,option_core
163  integer :: my_nspinor,nband_k,nband_cprj_k,npw_k,sender,me,master_spfftband,pnp_size
164  integer :: spaceComm_band,spaceComm_bandspinorfft,spaceComm_fft,spaceComm_kpt
165  integer :: spaceComm_spinor,spaceComm_bandspinor,spaceComm_spinorfft,spaceComm_w
166  logical :: already_has_nabla,cprj_paral_band,myband,mykpt,iomode_etsf_mpiio
167  logical :: i_am_master,i_am_master_kpt,i_am_master_band,i_am_master_spfft,nc_unlimited,store_half_dipoles
168  real(dp) :: cgnm1,cgnm2,cpnm1,cpnm2,cpnm11,cpnm22,cpnm12,cpnm21,cpnm_11m22,cpnm_21p12,cpnm_21m12
169  character(len=500) :: msg
170  type(nctkdim_t) :: nctkdim
171 !arrays
172  integer :: nc_count_5(5),nc_count_6(6),nc_start_5(5),nc_start_6(6),nc_stride_5(5),nc_stride_6(6),tmp_shape(3)
173  integer, ABI_CONTIGUOUS pointer :: kg_k(:,:)
174  real(dp) :: kpoint(3),tsec(2),nabla_ij(3)
175  real(dp),allocatable :: kpg_k(:,:)
176  real(dp),allocatable :: psinablapsi(:,:,:),psinablapsi_paw(:,:,:),psinablapsi_soc(:,:,:)
177  real(dp),pointer :: soc_ij(:,:,:)
178  type(coeff5_type),allocatable,target :: phisocphj(:)
179  type(pawcprj_type),pointer :: cprj_k(:,:),cprj_k_loc(:,:)
180  type(nctkarr_t) :: nctk_arrays(1)
181 
182 ! ************************************************************************
183 
184  DBG_ENTER("COLL")
185 
186 !Compatibility tests
187  ABI_CHECK(mkmem/=0,"mkmem==0 not supported anymore!")
188  ABI_CHECK(mpi_enreg%paral_spinor==0.or.dtset%pawspnorb==0,"spinor parallelization not supported with SOC!")
189 !  MJV 6/12/2008: looks like mpi_enreg may not be completely initialized here
190  if (xmpi_paral==1) then
191    tmp_shape = shape(mpi_enreg%proc_distrb)
192    if (nkpt > tmp_shape(1)) then
193      ABI_BUG('problem with proc_distrb!')
194    end if
195  end if
196 
197 !Init parallelism
198  spaceComm_w=mpi_enreg%comm_cell
199  if (mpi_enreg%paral_kgb==1) then
200    spaceComm_kpt=mpi_enreg%comm_kpt
201    spaceComm_fft=mpi_enreg%comm_fft
202    spaceComm_band=mpi_enreg%comm_band
203    spaceComm_spinor=mpi_enreg%comm_spinor
204    spaceComm_bandspinor=mpi_enreg%comm_bandspinor
205    spaceComm_spinorfft=mpi_enreg%comm_spinorfft
206    spaceComm_bandspinorfft=mpi_enreg%comm_bandspinorfft
207  else
208    spaceComm_kpt=mpi_enreg%comm_kpt
209    spaceComm_fft=xmpi_comm_self
210    spaceComm_band=mpi_enreg%comm_band
211    spaceComm_spinor=xmpi_comm_self
212    spaceComm_bandspinor=spaceComm_band
213    spaceComm_spinorfft=xmpi_comm_self
214    spaceComm_bandspinorfft=xmpi_comm_self
215  end if
216  me=xmpi_comm_rank(spaceComm_w)
217  i_am_master=(me==master)
218  i_am_master_kpt=(xmpi_comm_rank(spaceComm_kpt)==master)
219  i_am_master_band=(xmpi_comm_rank(spaceComm_band)==master)
220  i_am_master_spfft=(xmpi_comm_rank(spaceComm_spinorfft)==master)
221  my_nspinor=max(1,dtset%nspinor/mpi_enreg%nproc_spinor)
222 
223 !----------------------------------------------------------------------------------
224 !1- Opening of OPT file and header writing
225 !----------------------------------------------------------------------------------
226 
227 !I/O mode is netCDF or Fortran
228  iomode=merge(IO_MODE_ETSF,IO_MODE_FORTRAN_MASTER,dtset%iomode==IO_MODE_ETSF)
229 #ifdef HAVE_NETCDF
230  if (use_netcdf_forced) iomode=IO_MODE_ETSF
231 #endif
232 
233  !(master proc only)
234  if (i_am_master) then
235    fformopt=610 ; if (compute_half_dipoles) fformopt=620
236 !  ====> NETCDF format
237    if (iomode==IO_MODE_ETSF) then
238 #ifdef HAVE_NETCDF
239 !    Open/create nc file
240      NCF_CHECK(nctk_open_create(ncid,nctk_ncify(dtfil%fnameabo_app_opt),xmpi_comm_self))
241 !    Write header data
242      NCF_CHECK(hdr%ncwrite(ncid,fformopt,nc_define=.true.))
243 !    Define dims and array for dipole variables
244      nctk_arrays(1)%name="dipole_valence_valence"
245      nctk_arrays(1)%dtype="dp"
246      nc_unlimited=(use_netcdf_unlimited.and.(.not.(nctk_has_mpiio.and.use_netcdf_mpiio)))
247      if (nc_unlimited) then
248        nctkdim%name="unlimited_bands"
249        nctkdim%value=NF90_UNLIMITED
250        NCF_CHECK(nctk_def_dims(ncid,nctkdim))
251        nctk_arrays(1)%shape_str=&
252 &      "complex,number_of_cartesian_directions,max_number_of_states,number_of_kpoints,number_of_spins,unlimited_bands"
253      else if (compute_half_dipoles) then
254        nctkdim%name="max_number_of_state_pairs"
255        nctkdim%value=(mband*(mband+1))/2
256        NCF_CHECK(nctk_def_dims(ncid,nctkdim))
257        nctk_arrays(1)%shape_str=&
258 &      "complex,number_of_cartesian_directions,max_number_of_state_pairs,number_of_kpoints,number_of_spins"
259      else
260        nctk_arrays(1)%shape_str=&
261 &      "complex,number_of_cartesian_directions,max_number_of_states,max_number_of_states,number_of_kpoints,number_of_spins"
262      end if
263      NCF_CHECK(nctk_def_arrays(ncid, nctk_arrays))
264      NCF_CHECK(nctk_set_atomic_units(ncid, "dipole_valence_valence"))
265 !    Write eigenvalues
266      NCF_CHECK(nctk_set_datamode(ncid))
267      varid=nctk_idname(ncid,"eigenvalues")
268      NCF_CHECK(nf90_put_var(ncid,varid,reshape(eigen0,[mband,nkpt,nsppol])))
269      !Close file here because the rest has possibly to be written with collective I/O
270      NCF_CHECK(nf90_close(ncid))
271 #else
272      msg = "In order to use iomode=3 and prtnabla>0 together, NetCDF support must be enabled!"
273      ABI_ERROR(msg)
274 #endif
275 !  ====> Standard FORTRAN binary format
276    else if (iomode==IO_MODE_FORTRAN_MASTER) then
277      if (open_file(dtfil%fnameabo_app_opt,msg,newunit=ount,form="unformatted",status="unknown")/= 0) then
278        ABI_ERROR(msg)
279      end if
280      call hdr%fort_write(ount,fformopt,ierr,rewind=.true.)
281      write(ount)(eigen0(ib),ib=1,mband*nkpt*nsppol)
282    else
283      msg = "Wrong OPT file format!"
284      ABI_BUG(msg)
285    end if ! File format
286  end if ! master node
287  call xmpi_bcast(iomode,master,spaceComm_w,ierr)  ! Seems mandatory; why ?
288  iomode_etsf_mpiio=(iomode==IO_MODE_ETSF.and.nctk_has_mpiio.and.use_netcdf_mpiio)
289  nc_unlimited=(iomode==IO_MODE_ETSF.and.use_netcdf_unlimited.and.(.not.iomode_etsf_mpiio)) ! UNLIMITED not compatible with mpi-io
290  store_half_dipoles=(compute_half_dipoles.and.(.not.nc_unlimited))
291 
292 !----------------------------------------------------------------------------------
293 !2- Computation of on-site contribution: <phi_i|nabla|phi_j>-<tphi_i|nabla|tphi_j>
294 !----------------------------------------------------------------------------------
295 
296  already_has_nabla=all(pawtab(:)%has_nabla==2)
297  call pawnabla_init(mpsang,dtset%ntypat,pawrad,pawtab)
298  
299 !Compute spin-orbit contributions if necessary
300  if (dtset%pawspnorb==1) then
301    option_core=0
302    call pawnabla_soc_init(phisocphj,option_core,dtset%ixc,mpi_enreg%my_natom,natom,&
303 &       dtset%nspden,dtset%ntypat,pawang,pawrad,pawrhoij,pawtab,dtset%pawxcdev,&
304 &       dtset%spnorbscl,dtset%typat,dtset%xc_denpos,dtset%xc_taupos,znucl,&
305 &       comm_atom=mpi_enreg%comm_atom,mpi_atmtab=mpi_enreg%my_atmtab)
306  end if
307 
308 !----------------------------------------------------------------------------------
309 !3- Computation of <psi_n|-i.nabla|psi_m> for each k
310 !----------------------------------------------------------------------------------
311 
312 !Prepare valence-valence dipoles writing
313 !In case of netCDF access to OPT file, prepare collective I/O
314  if (iomode == IO_MODE_ETSF) then
315    if (iomode_etsf_mpiio) then
316      if (i_am_master_spfft) then
317        NCF_CHECK(nctk_open_modify(ncid,nctk_ncify(dtfil%fnameabo_app_opt),spaceComm_band))
318        varid=nctk_idname(ncid,"dipole_valence_valence")
319        if (xmpi_comm_size(spaceComm_w)>1) then
320          NCF_CHECK(nctk_set_collective(ncid,varid))
321        end if
322        NCF_CHECK(nctk_set_datamode(ncid))
323      end if
324    else if (i_am_master) then
325      NCF_CHECK(nctk_open_modify(ncid,nctk_ncify(dtfil%fnameabo_app_opt),xmpi_comm_self))
326      varid=nctk_idname(ncid,"dipole_valence_valence")
327      if (nctk_has_mpiio.and.(.not.use_netcdf_mpiio)) then
328        NCF_CHECK(nctk_set_collective(ncid,varid))
329      end if
330      NCF_CHECK(nctk_set_datamode(ncid))
331    end if     
332  end if
333  if (iomode_etsf_mpiio) then
334    !If MPI-IO, store only ib elements for each jb
335    ABI_MALLOC(psinablapsi,(2,3,mband))
336    ABI_MALLOC(psinablapsi_paw,(2,3,mband))
337    if (dtset%pawspnorb==1) then
338      ABI_MALLOC(psinablapsi_soc,(2,3,mband))
339    end if
340  else
341    !If not, store all (ib,jb) pairs (or half)
342    bsize=mband**2 ; if (store_half_dipoles) bsize=(mband*(mband+1))/2
343    ABI_MALLOC(psinablapsi,(2,3,bsize))
344    ABI_MALLOC(psinablapsi_paw,(2,3,bsize))
345    if (dtset%pawspnorb==1) then
346      ABI_MALLOC(psinablapsi_soc,(2,3,bsize))
347    end if
348    psinablapsi=zero
349  end if
350  pnp_size=size(psinablapsi)
351  
352 !Determine if cprj datastructure is distributed over bands
353  mband_cprj=mcprj/(my_nspinor*mkmem*nsppol)
354  cprj_paral_band=(mband_cprj<mband)
355 
356 !LOOP OVER SPINS
357  ibg=0;icg=0
358  bdtot_index=0
359  do isppol=1,nsppol
360 
361 !  LOOP OVER k POINTS
362    ikg=0
363    do ikpt=1,nkpt
364 
365      etiq=ikpt+(isppol-1)*nkpt
366      nband_k=dtset%nband(ikpt+(isppol-1)*nkpt)
367      master_spfftband=minval(mpi_enreg%proc_distrb(ikpt,1:nband_k,isppol))
368 
369 !    Select k-points for current proc
370      mykpt=.not.(proc_distrb_cycle(mpi_enreg%proc_distrb,ikpt,1,nband_k,isppol,mpi_enreg%me_kpt))
371      if (mykpt) then
372 
373 !      Data depending on k-point
374        npw_k=npwarr(ikpt)
375        istwf_k=dtset%istwfk(ikpt)
376        cplex=2;if (istwf_k>1) cplex=1
377        kpoint(:)=dtset%kptns(:,ikpt)
378 
379 !      Extract cprj for this k-point
380        nband_cprj_k=nband_k;if (cprj_paral_band) nband_cprj_k=nband_k/mpi_enreg%nproc_band
381        if (mkmem*nsppol/=1) then
382          iorder_cprj=0
383          ABI_MALLOC(cprj_k_loc,(natom,my_nspinor*nband_cprj_k))
384          call pawcprj_alloc(cprj_k_loc,0,dimcprj)
385          call pawcprj_get(atindx1,cprj_k_loc,cprj,natom,1,ibg,ikpt,iorder_cprj,isppol,&
386 &         mband_cprj,mkmem,natom,nband_cprj_k,nband_cprj_k,my_nspinor,nsppol,dtfil%unpaw,&
387 &         mpicomm=mpi_enreg%comm_kpt,proc_distrb=mpi_enreg%proc_distrb)
388        else
389          cprj_k_loc => cprj
390        end if
391 
392 !      if cprj are distributed over bands, gather them (because we need to mix bands)
393        if (cprj_paral_band) then
394          ABI_MALLOC(cprj_k,(natom,my_nspinor*nband_k))
395          call pawcprj_alloc(cprj_k,0,dimcprj)
396          call pawcprj_mpi_allgather(cprj_k_loc,cprj_k,natom, &
397 &             my_nspinor*nband_cprj_k,my_nspinor*mpi_enreg%bandpp,&
398 &         dimcprj,0,mpi_enreg%nproc_band,mpi_enreg%comm_band,ierr,rank_ordered=.false.)
399        else
400          cprj_k => cprj_k_loc
401        end if
402 
403 !      Compute k+G in cartesian coordinates
404        ABI_MALLOC(kpg_k,(3,npw_k*dtset%nspinor))
405        kg_k => kg(:,1+ikg:npw_k+ikg)
406        do ipw=1,npw_k
407          kpg_k(1,ipw)=(kpoint(1)+kg_k(1,ipw))*gprimd(1,1) &
408 &                    +(kpoint(2)+kg_k(2,ipw))*gprimd(1,2) &
409 &                    +(kpoint(3)+kg_k(3,ipw))*gprimd(1,3)
410          kpg_k(2,ipw)=(kpoint(1)+kg_k(1,ipw))*gprimd(2,1) &
411 &                    +(kpoint(2)+kg_k(2,ipw))*gprimd(2,2) &
412 &                    +(kpoint(3)+kg_k(3,ipw))*gprimd(2,3)
413          kpg_k(3,ipw)=(kpoint(1)+kg_k(1,ipw))*gprimd(3,1) &
414 &                    +(kpoint(2)+kg_k(2,ipw))*gprimd(3,2) &
415 &                    +(kpoint(3)+kg_k(3,ipw))*gprimd(3,3)
416        end do
417        kpg_k=two_pi*kpg_k
418        if (dtset%nspinor==2) kpg_k(1:3,npw_k+1:2*npw_k)=kpg_k(1:3,1:npw_k)
419 
420 !      Loops over bands
421        do jb=1,nband_k
422          jwavef=(jb-1)*npw_k*my_nspinor+icg
423          !If MPI-IO, compute all (ib,jb) pairs ; if not, compute only ib<=jb
424          ibmax=merge(nband_k,jb,iomode_etsf_mpiio)
425          !If MPI-IO, store only ib elements for each jb ; if not, store all (ib,jb) pairs
426          my_jb=merge(1,jb,iomode_etsf_mpiio)
427 
428 !        Fill output arrays with zeros
429          if (store_half_dipoles) then
430            jbshift=(my_jb*(my_jb-1))/2 ; bsize=nband_k
431          else
432            jbshift=(my_jb-1)*mband ; bsize=mband
433          end if
434          psinablapsi(:,:,jbshift+1:jbshift+bsize)=zero
435          psinablapsi_paw(:,:,jbshift+1:jbshift+bsize)=zero
436          if (dtset%pawspnorb==1) psinablapsi_soc(:,:,jbshift+1:jbshift+bsize)=zero
437            
438 !        2-A Computation of <psi_tild_n|-i.nabla|psi_tild_m>
439 !        ----------------------------------------------------------------------------------
440 !        Note: <psi_nk|-i.nabla|psi_mk> => Sum_g[ <G|Psi_nk>^* <G|Psi_mk> G ]
441 
442 !        Select bands for current proc
443          myband=.true.
444          if (xmpi_paral==1.and.mpi_enreg%paral_kgb/=1.and.(.not.iomode_etsf_mpiio)) then
445            myband=(abs(mpi_enreg%proc_distrb(ikpt,jb,isppol)-mpi_enreg%me_kpt)==0)
446          end if
447          if (myband) then
448 
449            do ib=1,ibmax
450              iwavef=(ib-1)*npw_k*my_nspinor+icg
451 
452 !            (C_nk^*)*C_mk*(k+g) is expressed in cartesian coordinates
453              if (istwf_k>1) then
454                !In this case (istwfk>1): Sum_g>=g0[ 2i.Im(<G|Psi_nk>^* <G|Psi_mk> G) ]
455                !G=k+g=0 term is included but do not contribute
456                do ipw=1,npw_k*my_nspinor
457                  cgnm2=two*(cg(1,ipw+iwavef)*cg(2,ipw+jwavef)-cg(2,ipw+iwavef)*cg(1,ipw+jwavef))
458                  psinablapsi(2,1:3,jbshift+ib)=psinablapsi(2,1:3,jbshift+ib)+cgnm2*kpg_k(1:3,ipw)
459                end do
460              else
461                do ipw=1,npw_k*my_nspinor
462                  cgnm1=cg(1,ipw+iwavef)*cg(1,ipw+jwavef)+cg(2,ipw+iwavef)*cg(2,ipw+jwavef)
463                  cgnm2=cg(1,ipw+iwavef)*cg(2,ipw+jwavef)-cg(2,ipw+iwavef)*cg(1,ipw+jwavef)
464                  psinablapsi(1,1:3,jbshift+ib)=psinablapsi(1,1:3,jbshift+ib)+cgnm1*kpg_k(1:3,ipw)
465                  psinablapsi(2,1:3,jbshift+ib)=psinablapsi(2,1:3,jbshift+ib)+cgnm2*kpg_k(1:3,ipw)
466                end do
467              end if
468 
469 !            Second half of the (n,m) matrix
470              if ((ib/=jb).and.(.not.store_half_dipoles).and.(.not.iomode_etsf_mpiio)) then
471                ibshift=(ib-1)*mband
472                psinablapsi(1,1:3,ibshift+jb)= psinablapsi(1,1:3,jbshift+ib)
473                psinablapsi(2,1:3,ibshift+jb)=-psinablapsi(2,1:3,jbshift+ib)
474              end if
475 
476            end do ! ib
477 
478 !          Reduction in case of parallelism
479            if (iomode_etsf_mpiio) then
480              call timab(48,1,tsec)
481              if (mpi_enreg%paral_kgb==1) then
482                call xmpi_sum_master(psinablapsi,master,spaceComm_spinorfft,ierr)
483              end if
484              if (i_am_master_spfft) then
485                call xmpi_sum(psinablapsi,spaceComm_band,ierr)
486              end if
487              call timab(48,2,tsec)
488            end if
489 
490          end if ! myband
491 
492        
493 !        2-B Computation of <psi_n|p_i><p_j|psi_m>(<phi_i|-i.nabla|phi_j>-<tphi_i|-i.nabla|tphi_j>)
494 !        ----------------------------------------------------------------------------------
495 !        Non relativistic contribution
496 !        Note: <psi|-i.nabla|psi_mk>
497 !              => -i Sum_ij[ <p_i|Psi_nk>^* <p_j|Psi_mk> (<Phi_i|Nabla|Phi_j>-<tPhi_i|Nabla|tPhi_j>) ]
498 
499 !        Select bands for current proc
500          myband=.true.
501          if (mpi_enreg%paral_kgb==1) then
502            myband=(mod(jb-1,mpi_enreg%nproc_band)==mpi_enreg%me_band)
503          else if (xmpi_paral==1) then
504            myband=(abs(mpi_enreg%proc_distrb(ikpt,jb,isppol)-mpi_enreg%me_kpt)==0)
505          end if
506          if (myband) then
507 
508            do ib=1,ibmax          
509 
510              ibsp=(ib-1)*my_nspinor ; jbsp=(jb-1)*my_nspinor
511              do ispinor=1,my_nspinor
512                ibsp=ibsp+1;jbsp=jbsp+1
513                if (cplex==1) then
514                  do iatom=1,natom
515                    itypat=dtset%typat(iatom)
516                    lmn_size=pawtab(itypat)%lmn_size
517                    do jlmn=1,lmn_size
518                      do ilmn=1,lmn_size                  
519                        nabla_ij(:)=pawtab(itypat)%nabla_ij(:,ilmn,jlmn)
520                        if (ib>jb) nabla_ij(:)=-pawtab(itypat)%nabla_ij(:,jlmn,ilmn)
521                        cpnm1=cprj_k(iatom,ibsp)%cp(1,ilmn)*cprj_k(iatom,jbsp)%cp(1,jlmn)
522                        if (dtset%nspinor==2) cpnm1=cpnm1+cprj_k(iatom,ibsp)%cp(2,ilmn)*cprj_k(iatom,jbsp)%cp(2,jlmn)
523                        psinablapsi_paw(2,:,jbshift+ib)=psinablapsi_paw(2,:,jbshift+ib)-cpnm1*nabla_ij(:)
524                      end do !ilmn
525                    end do !jlmn
526                  end do !iatom
527                else
528                  do iatom=1,natom
529                    itypat=dtset%typat(iatom)
530                    lmn_size=pawtab(itypat)%lmn_size
531                    do jlmn=1,lmn_size
532                      do ilmn=1,lmn_size
533                        nabla_ij(:)=pawtab(itypat)%nabla_ij(:,ilmn,jlmn)
534                        if (ib>jb) nabla_ij(:)=-pawtab(itypat)%nabla_ij(:,jlmn,ilmn)
535                        cpnm1=(cprj_k(iatom,ibsp)%cp(1,ilmn)*cprj_k(iatom,jbsp)%cp(1,jlmn) &
536 &                            +cprj_k(iatom,ibsp)%cp(2,ilmn)*cprj_k(iatom,jbsp)%cp(2,jlmn))
537                        cpnm2=(cprj_k(iatom,ibsp)%cp(1,ilmn)*cprj_k(iatom,jbsp)%cp(2,jlmn) &
538 &                            -cprj_k(iatom,ibsp)%cp(2,ilmn)*cprj_k(iatom,jbsp)%cp(1,jlmn))
539                        psinablapsi_paw(1,:,jbshift+ib)=psinablapsi_paw(1,:,jbshift+ib)+cpnm2*nabla_ij(:)
540                        psinablapsi_paw(2,:,jbshift+ib)=psinablapsi_paw(2,:,jbshift+ib)-cpnm1*nabla_ij(:)
541                      end do !ilmn
542                    end do !jlmn
543                  end do !iatom
544                end if
545              end do !ispinor
546 
547 !        2-C Computation of Spin-orbit coupling contribution:
548 !             Sum_ij,ss'[<psi_n,s|p_i><p_j|psi_m,s'>(<phi_i|1/4 Alpha^2 (Sigma^ss' X dV/dr)|phi_j>]
549 !        ----------------------------------------------------------------------------------
550              if (dtset%pawspnorb==1) then
551 !              Add: Sum_ij,ss'[<Psi^s_n|p_i><p_j|Psi^s'_m> (Sigma^ss' X g_ij)]
552 !                  =Sum_ij[ (<Psi^up_n|p_i><p_j|Psi^up_m>-<Psi^dn_n|p_i><p_j|Psi^dn_m>) (Sigma^up-up     X g_ij)
553 !                          +(<Psi^dn_n|p_i><p_j|Psi^up_m>+<Psi^up_n|p_i><p_j|Psi^dn_m>) (Re{Sigma^dn-up} X g_ij)
554 !                          +(<Psi^dn_n|p_i><p_j|Psi^up_m>-<Psi^up_n|p_i><p_j|Psi^dn_m>) (Im{Sigma^dn-up} X g_ij) ]
555 !               where: g_ij = <Phi_i| 1/4 Alpha^2 dV/dr vec(r)/r) |Phi_j>
556 !              Note that:
557 !                phisocphj(:)%value(re:im,1,idir,ilmn,jlmn) is (Sigma^up-up X g_ij)
558 !                phisocphj(:)%value(re:im,2,idir,ilmn,jlmn) is (Sigma^dn-up X g_ij)
559 !              Not compatible with parallelization over spinors
560                ibsp=1+(ib-1)*dtset%nspinor ; jbsp=1+(jb-1)*dtset%nspinor
561                do iatom=1,natom
562                  itypat=dtset%typat(iatom)
563                  lmn_size=pawtab(itypat)%lmn_size
564                  do jlmn=1,lmn_size
565                    do ilmn=1,lmn_size
566                      soc_ij => phisocphj(iatom)%value(:,:,:,ilmn,jlmn)
567                      !Contribution from real part of <Psi^s_n|p_i><p_j|Psi^s'_m>
568                      cpnm11=cprj_k(iatom,ibsp  )%cp(1,ilmn)*cprj_k(iatom,jbsp  )%cp(1,jlmn) &
569 &                          +cprj_k(iatom,ibsp  )%cp(2,ilmn)*cprj_k(iatom,jbsp  )%cp(2,jlmn)
570                      cpnm22=cprj_k(iatom,ibsp+1)%cp(1,ilmn)*cprj_k(iatom,jbsp+1)%cp(1,jlmn) &
571 &                          +cprj_k(iatom,ibsp+1)%cp(2,ilmn)*cprj_k(iatom,jbsp+1)%cp(2,jlmn)
572                      cpnm12=cprj_k(iatom,ibsp  )%cp(1,ilmn)*cprj_k(iatom,jbsp+1)%cp(1,jlmn) &
573 &                          +cprj_k(iatom,ibsp  )%cp(2,ilmn)*cprj_k(iatom,jbsp+1)%cp(2,jlmn)
574                      cpnm21=cprj_k(iatom,ibsp+1)%cp(1,ilmn)*cprj_k(iatom,jbsp  )%cp(1,jlmn) &
575 &                          +cprj_k(iatom,ibsp+1)%cp(2,ilmn)*cprj_k(iatom,jbsp  )%cp(2,jlmn)
576                      cpnm_11m22=cpnm11-cpnm22
577                      cpnm_21p12=cpnm21+cpnm12
578                      cpnm_21m12=cpnm21-cpnm12
579                      do idir=1,3
580                        psinablapsi_soc(1,idir,jbshift+ib)=psinablapsi_soc(1,idir,jbshift+ib) &
581 &                             +soc_ij(1,1,idir)*cpnm_11m22+soc_ij(1,2,idir)*cpnm_21p12
582                        psinablapsi_soc(2,idir,jbshift+ib)=psinablapsi_soc(2,idir,jbshift+ib) &
583 &                             +soc_ij(2,2,idir)*cpnm_21m12
584                      end do
585                      !Contribution from imaginary part of <Psi^s_n|p_i><p_j|Psi^s'_m>
586                      cpnm11=cprj_k(iatom,ibsp  )%cp(1,ilmn)*cprj_k(iatom,jbsp  )%cp(2,jlmn) &
587 &                          -cprj_k(iatom,ibsp  )%cp(2,ilmn)*cprj_k(iatom,jbsp  )%cp(1,jlmn)
588                      cpnm22=cprj_k(iatom,ibsp+1)%cp(1,ilmn)*cprj_k(iatom,jbsp+1)%cp(2,jlmn) &
589 &                          -cprj_k(iatom,ibsp+1)%cp(2,ilmn)*cprj_k(iatom,jbsp+1)%cp(1,jlmn)
590                      cpnm12=cprj_k(iatom,ibsp  )%cp(1,ilmn)*cprj_k(iatom,jbsp+1)%cp(2,jlmn) &
591 &                          -cprj_k(iatom,ibsp  )%cp(2,ilmn)*cprj_k(iatom,jbsp+1)%cp(1,jlmn)
592                      cpnm21=cprj_k(iatom,ibsp+1)%cp(1,ilmn)*cprj_k(iatom,jbsp  )%cp(2,jlmn) &
593 &                          -cprj_k(iatom,ibsp+1)%cp(2,ilmn)*cprj_k(iatom,jbsp  )%cp(1,jlmn)
594                      cpnm_11m22=cpnm11-cpnm22
595                      cpnm_21p12=cpnm21+cpnm12
596                      cpnm_21m12=cpnm21-cpnm12
597                      do idir=1,3
598                        psinablapsi_soc(1,idir,jbshift+ib)=psinablapsi_soc(1,idir,jbshift+ib) &
599 &                          -soc_ij(2,2,idir)*cpnm_21m12
600                        psinablapsi_soc(2,idir,jbshift+ib)=psinablapsi_soc(2,idir,jbshift+ib) &
601 &                          +soc_ij(1,1,idir)*cpnm_11m22+soc_ij(1,2,idir)*cpnm_21p12
602                      end do
603                    end do ! ilmn
604                  end do ! jlmn
605                end do ! iatom
606              end if ! pawspnorb
607 
608 !            Second half of the (n,m) matrix
609              if ((ib/=jb).and.(.not.store_half_dipoles).and.(.not.iomode_etsf_mpiio)) then
610                ibshift=(ib-1)*mband
611                psinablapsi_paw(1,1:3,ibshift+jb)= psinablapsi_paw(1,1:3,jbshift+ib)
612                psinablapsi_paw(2,1:3,ibshift+jb)=-psinablapsi_paw(2,1:3,jbshift+ib)
613                if (dtset%pawspnorb==1) then
614                  psinablapsi_soc(1,1:3,ibshift+jb)= psinablapsi_soc(1,1:3,jbshift+ib)
615                  psinablapsi_soc(2,1:3,ibshift+jb)=-psinablapsi_soc(2,1:3,jbshift+ib)
616                end if
617              end if
618 
619            end do ! ib loop
620 
621            if (iomode_etsf_mpiio.and.mpi_enreg%paral_spinor==1) then
622              call timab(48,1,tsec)
623              call xmpi_sum_master(psinablapsi_paw,master,spaceComm_spinor,ierr)
624              call timab(48,2,tsec)
625            end if
626 
627          end if ! myband
628 
629 !        Write to OPT file in case of MPI-IO
630          if (iomode_etsf_mpiio.and.i_am_master_spfft) then
631            if (myband) then
632              psinablapsi=psinablapsi+psinablapsi_paw
633              if (dtset%pawspnorb==1) psinablapsi=psinablapsi+psinablapsi_soc
634            end if       
635            if (store_half_dipoles) then
636              nc_start_5=[1,1,(jb*(jb-1))/2+1,ikpt,isppol];nc_stride_5=[1,1,1,1,1]
637              nc_count_5=[0,0,0,0,0];if (myband) nc_count_5=[2,3,jb,1,1] 
638 #ifdef HAVE_NETCDF
639              NCF_CHECK(nf90_put_var(ncid,varid,psinablapsi,start=nc_start_5,stride=nc_stride_5,count=nc_count_5))
640 #endif
641            else
642              nc_start_6=[1,1,1,jb,ikpt,isppol];nc_stride_6=[1,1,1,1,1,1]           
643              nc_count_6=[0,0,0,0,0,0];if (myband) nc_count_6=[2,3,mband,1,1,1]
644 #ifdef HAVE_NETCDF
645              NCF_CHECK(nf90_put_var(ncid,varid,psinablapsi,start=nc_start_6,stride=nc_stride_6,count=nc_count_6))
646 #endif
647            end if
648          end if
649 
650        end do ! jb
651 
652        if (mkmem/=0) then
653          ibg = ibg +       my_nspinor*nband_cprj_k
654          icg = icg + npw_k*my_nspinor*nband_k
655          ikg = ikg + npw_k
656        end if
657 
658        if (cprj_paral_band) then
659          call pawcprj_free(cprj_k)
660          ABI_FREE(cprj_k)
661        end if
662        if (mkmem*nsppol/=1) then
663          call pawcprj_free(cprj_k_loc)
664          ABI_FREE(cprj_k_loc)
665        end if
666        ABI_FREE(kpg_k)
667 
668 !      Write to OPT file if not MPI-IO
669 
670 !      >>> Reduction in case of parallelism
671        if (.not.iomode_etsf_mpiio) then
672          call timab(48,1,tsec)
673          call xmpi_sum_master(psinablapsi,master,spaceComm_bandspinorfft,ierr)
674          call xmpi_sum_master(psinablapsi_paw,master,spaceComm_bandspinor,ierr)
675          call timab(48,2,tsec)
676          psinablapsi=psinablapsi+psinablapsi_paw
677          if (dtset%pawspnorb==1) then
678            call xmpi_sum_master(psinablapsi_soc,master,spaceComm_band,ierr)
679            psinablapsi=psinablapsi+psinablapsi_soc
680          end if
681        end if
682 
683 !      >>> This my kpt and I am the master node: I write the data    
684        if (.not.iomode_etsf_mpiio) then
685          if (i_am_master) then
686            if (iomode==IO_MODE_ETSF) then
687 #ifdef HAVE_NETCDF
688              if (nc_unlimited) then
689                nc_start_6=[1,1,1,ikpt,isppol,1] ; nc_count_6=[2,3,mband,1,1,mband] ; nc_stride_6=[1,1,1,1,1,1] 
690                NCF_CHECK(nf90_put_var(ncid,varid,psinablapsi,start=nc_start_6,stride=nc_stride_6,count=nc_count_6))
691              else if (.not.store_half_dipoles) then
692                nc_start_6=[1,1,1,1,ikpt,isppol] ; nc_count_6=[2,3,mband,mband,1,1] ; nc_stride_6=[1,1,1,1,1,1] 
693                NCF_CHECK(nf90_put_var(ncid,varid,psinablapsi,start=nc_start_6,stride=nc_stride_6,count=nc_count_6))
694              else
695                nc_start_5=[1,1,1,ikpt,isppol] ; nc_count_5=[2,3,(mband*(mband+1))/2,1,1] ; nc_stride_5=[1,1,1,1,1] 
696                NCF_CHECK(nf90_put_var(ncid,varid,psinablapsi,start=nc_start_5,stride=nc_stride_5,count=nc_count_5))
697              end if
698 #endif
699            else
700              bsize=nband_k**2;if (store_half_dipoles) bsize=(nband_k*(nband_k+1))/2
701              write(ount)(psinablapsi(1:2,1,ib),ib=1,bsize)
702              write(ount)(psinablapsi(1:2,2,ib),ib=1,bsize)
703              write(ount)(psinablapsi(1:2,3,ib),ib=1,bsize)
704            end if
705 
706 !        >>> This my kpt and I am not the master node: I send the data    
707          else if (i_am_master_band.and.i_am_master_spfft) then
708            if (mpi_enreg%me_kpt/=master_spfftband) then
709              ABI_BUG('Problem with band communicator!')
710            end if
711            call xmpi_exch(psinablapsi,pnp_size,mpi_enreg%me_kpt,psinablapsi,master,spaceComm_kpt,etiq,ierr)
712          end if
713        end if  
714 
715 !    >>> This is not my kpt and I am the master node: I receive the data and I write    
716      elseif ((.not.iomode_etsf_mpiio).and.i_am_master) then ! mykpt
717        sender=master_spfftband
718        call xmpi_exch(psinablapsi,pnp_size,sender,psinablapsi,master,spaceComm_kpt,etiq,ierr)
719        if (iomode==IO_MODE_ETSF) then
720 #ifdef HAVE_NETCDF
721          if (nc_unlimited) then
722            nc_start_6=[1,1,1,ikpt,isppol,1] ; nc_count_6=[2,3,mband,1,1,mband] ; nc_stride_6=[1,1,1,1,1,1] 
723            NCF_CHECK(nf90_put_var(ncid,varid,psinablapsi,start=nc_start_6,stride=nc_stride_6,count=nc_count_6))
724          else if (.not.store_half_dipoles) then
725            nc_start_6=[1,1,1,1,ikpt,isppol] ; nc_count_6=[2,3,mband,mband,1,1] ; nc_stride_6=[1,1,1,1,1,1] 
726            NCF_CHECK(nf90_put_var(ncid,varid,psinablapsi,start=nc_start_6,stride=nc_stride_6,count=nc_count_6))
727          else
728            nc_start_5=[1,1,1,ikpt,isppol] ; nc_count_5=[2,3,(mband*(mband+1))/2,1,1] ; nc_stride_5=[1,1,1,1,1] 
729            NCF_CHECK(nf90_put_var(ncid,varid,psinablapsi,start=nc_start_5,stride=nc_stride_5,count=nc_count_5))
730          end if
731 #endif
732        else
733          bsize=nband_k**2;if (store_half_dipoles) bsize=(nband_k*(nband_k+1))/2
734          write(ount)(psinablapsi(1:2,1,ib),ib=1,bsize)
735          write(ount)(psinablapsi(1:2,2,ib),ib=1,bsize)
736          write(ount)(psinablapsi(1:2,3,ib),ib=1,bsize)
737        end if
738      end if ! mykpt
739 
740      bdtot_index=bdtot_index+nband_k
741 
742 !    End loop on spin,kpt
743    end do ! ikpt
744  end do !isppol
745 
746 !Close file
747  if (i_am_master.or.(iomode_etsf_mpiio.and.i_am_master_spfft)) then
748    if (iomode==IO_MODE_ETSF) then
749 #ifdef HAVE_NETCDF
750      NCF_CHECK(nf90_close(ncid))
751 #endif
752    else
753      ierr=close_unit(ount,msg)
754      ABI_CHECK(ierr==0,"Error while closing OPT file")
755    end if
756  end if
757 
758 !Datastructures deallocations
759  ABI_FREE(psinablapsi)
760  ABI_FREE(psinablapsi_paw)
761  if (dtset%pawspnorb==1) then
762    ABI_FREE(psinablapsi_soc)
763    do iatom=1,natom
764      ABI_FREE(phisocphj(iatom)%value)
765    end do
766    ABI_FREE(phisocphj)
767  end if
768  if (.not.already_has_nabla) then
769    do itypat=1,dtset%ntypat
770      if (allocated(pawtab(itypat)%nabla_ij)) then
771        ABI_FREE(pawtab(itypat)%nabla_ij)
772        pawtab(itypat)%has_nabla=0
773      end if
774    end do
775  end if
776 
777  DBG_EXIT("COLL")
778 
779  end subroutine optics_paw

m_paw_optics/optics_paw_core [ Functions ]

[ Top ] [ m_paw_optics ] [ Functions ]

NAME

 optics_paw_core

FUNCTION

 Compute matrix elements need for X spectr. (in the PAW context) and store them in a file
  Matrix elements = <Phi_core|Nabla|Phi_j>

COPYRIGHT

 Copyright (C) 2005-2024 ABINIT group (SM,MT,NB)
 This file is distributed under the terms of the
 GNU General Public License, see ~ABINIT/COPYING
 or http://www.gnu.org/copyleft/gpl.txt .

INPUTS

  atindx1(natom)=index table for atoms, inverse of atindx (see gstate.f)
  cprj(natom,mcprj)= <p_lmn|Cnk> coefficients for each WF |Cnk> and each |p_lmn> non-local projector
  dimcprj(natom)=array of dimensions of array cprj (not ordered)
  dtfil <type(datafiles_type)>=variables related to files
  dtset <type(dataset_type)>=all input variables for this dataset
  filpsp(ntypat)=name(s) of the pseudopotential file(s)
  mband=maximum number of bands
  mcprj=size of projected wave-functions array (cprj) =nspinor*mband*mkmem*nsppol
  mkmem =number of k points treated by this node.
  mpi_enreg=information about MPI parallelization
  mpsang =1+maximum angular momentum for nonlocal pseudopotentials
  natom=number of atoms in cell.
  nkpt=number of k points.
  nsppol=1 for unpolarized, 2 for spin-polarized
  pawang <type(pawang_type)>= PAW ANGular mesh discretization and related data
  pawrad(ntypat) <type(pawrad_type)>=paw radial mesh and related data
  pawrhoij(my_natom) <type(pawrhoij_type)>= PAW rhoij occupancies and related data
  pawtab(ntypat) <type(pawtab_type)>=paw tabulated starting data
  znucl(ntypat)=atomic number of atom type

OUTPUT

  (only writing in a file)

SOURCE

 824  subroutine optics_paw_core(atindx1,cprj,dimcprj,dtfil,dtset,eigen0,filpsp,hdr,&
 825 &               mband,mcprj,mkmem,mpi_enreg,mpsang,natom,nkpt,nsppol,&
 826 &               pawang,pawrad,pawrhoij,pawtab,znucl)
 827 
 828 !Arguments ------------------------------------
 829 !scalars
 830  integer,intent(in) :: mband,mcprj,mkmem,mpsang,natom,nkpt,nsppol
 831  type(MPI_type),intent(in) :: mpi_enreg
 832  type(datafiles_type),intent(in) :: dtfil
 833  type(dataset_type),intent(in) :: dtset
 834  type(hdr_type),intent(inout) :: hdr
 835  type(pawang_type),intent(in) :: pawang
 836 !arrays
 837  integer,intent(in) :: atindx1(natom),dimcprj(natom)
 838  character(len=fnlen),intent(in) :: filpsp(dtset%ntypat)
 839  real(dp),intent(in) :: eigen0(mband*nkpt*nsppol),znucl(dtset%ntypat)
 840  type(pawcprj_type),target,intent(inout) :: cprj(natom,mcprj)
 841  type(pawrad_type),intent(in) :: pawrad(dtset%ntypat)
 842  type(pawrhoij_type),intent(inout) :: pawrhoij(mpi_enreg%my_natom)
 843  type(pawtab_type),target,intent(inout) :: pawtab(dtset%ntypat)
 844 
 845 !Local variables-------------------------------
 846 !scalars
 847  integer,parameter :: master=0
 848  integer :: bdtot_index,cplex,etiq,iatom,ic,ibg,idir
 849  integer :: ierr,ikpt,ilmn,iln,ount,is,my_jb
 850  integer :: iorder_cprj,ispinor,isppol,istwf_k,itypat
 851  integer :: jb,jbsp,jlmn,lmn_size,lmncmax,mband_cprj,ncid,varid
 852  integer :: me,my_nspinor,nband_cprj_k,option_core,pnp_size
 853  integer :: nband_k,nphicor,ncorespinor,sender,iomode,fformopt,master_spfftband
 854  integer :: spaceComm_band,spaceComm_bandspinorfft,spaceComm_fft,spaceComm_kpt
 855  integer :: spaceComm_spinor,spaceComm_bandspinor,spaceComm_spinorfft,spaceComm_w
 856  logical :: already_has_nabla,cprj_paral_band,ex,mykpt,myband
 857  logical :: iomode_etsf_mpiio,abinitcorewf,use_spinorbit,xmlcorewf
 858  logical :: i_am_master,i_am_master_band,i_am_master_spfft
 859  character(len=fnlen) :: filecore
 860  real(dp) :: cpnm1,cpnm2
 861  character(len=500) :: msg
 862 !arrays
 863  integer :: nc_count(7),nc_start(7),nc_stride(7),tmp_shape(3)
 864  integer,allocatable :: indlmn_cor(:,:),lcor(:),ncor(:),kappacor(:)
 865  real(dp) :: tsec(2)
 866  real(dp),allocatable :: energy_cor(:),phi_cor(:,:)
 867  real(dp),allocatable :: psinablapsi(:,:,:,:,:),psinablapsi_soc(:,:,:,:,:)
 868  real(dp),pointer :: soc_ij(:,:,:)
 869  type(coeff5_type),allocatable,target :: phisocphj(:)
 870  type(pawcprj_type),pointer :: cprj_k(:,:),cprj_k_loc(:,:)
 871  type(nctkdim_t) :: ncdims(3)
 872  type(nctkarr_t) :: nctk_arrays(5)
 873 
 874 ! ************************************************************************
 875 
 876  DBG_ENTER("COLL")
 877 
 878 !Compatibility tests
 879  msg="mkmem==0 not supported anymore!"
 880  ABI_CHECK(mkmem/=0,msg)
 881 !Probably should check for spinor parallelism, because thats likely to not work correctly
 882  msg="Spinor parallelism not implemented for optics_paw_core!"
 883  ABI_CHECK(dtset%npspinor==1,msg)
 884 !Is mpi_enreg initialized?
 885  if (xmpi_paral==1) then
 886    tmp_shape = shape(mpi_enreg%proc_distrb)
 887    if (nkpt > tmp_shape(1)) then
 888      ABI_BUG('problem with proc_distrb!')
 889    end if
 890  end if
 891 
 892 !Init parallelism
 893  spaceComm_w=mpi_enreg%comm_cell
 894  if (mpi_enreg%paral_kgb==1) then
 895    spaceComm_kpt=mpi_enreg%comm_kpt
 896    spaceComm_fft=mpi_enreg%comm_fft
 897    spaceComm_band=mpi_enreg%comm_band
 898    spaceComm_spinor=mpi_enreg%comm_spinor
 899    spaceComm_bandspinor=mpi_enreg%comm_bandspinor
 900    spaceComm_spinorfft=mpi_enreg%comm_spinorfft
 901    spaceComm_bandspinorfft=mpi_enreg%comm_bandspinorfft
 902  else
 903    spaceComm_kpt=mpi_enreg%comm_kpt
 904    spaceComm_fft=xmpi_comm_self
 905    spaceComm_band=mpi_enreg%comm_band
 906    spaceComm_spinor=xmpi_comm_self
 907    spaceComm_bandspinor=spaceComm_band
 908    spaceComm_spinorfft=xmpi_comm_self
 909    spaceComm_bandspinorfft=xmpi_comm_self
 910  end if
 911  me=xmpi_comm_rank(spaceComm_w)
 912  i_am_master=(me==master)
 913  i_am_master_band=(xmpi_comm_rank(spaceComm_band)==master)
 914  i_am_master_spfft=(xmpi_comm_rank(spaceComm_spinorfft)==master)
 915  my_nspinor=max(1,dtset%nspinor/mpi_enreg%nproc_spinor)
 916 
 917 !------------------------------------------------------------------------------------------------
 918 !1- Reading of core wavefunctions
 919 !------------------------------------------------------------------------------------------------
 920 
 921 !Note: core WF is read for itypat=1
 922 !At present, impose 2-spinor simulataneously for core anf valence WF
 923  ncorespinor=merge(2,1,dtset%pawspnorb==1.or.dtset%nspinor==2)
 924  filecore=trim(filpsp(1)) ; iln=len(trim(filecore))
 925  abinitcorewf=.false. ; if (iln>3) abinitcorewf=(filecore(iln-6:iln)=='.abinit')
 926  xmlcorewf=.false. ; if (iln>3) xmlcorewf=(filecore(iln-3:iln)=='.xml')
 927  if ((.not.xmlcorewf).and.(.not.abinitcorewf)) filecore=filecore(1:iln)//'.corewf'
 928  if (abinitcorewf) filecore=filecore(1:iln-6)//'corewf.abinit'
 929  if (xmlcorewf) filecore=filecore(1:iln-3)//'corewf.xml'
 930  inquire(file=filecore,exist=ex)
 931 
 932 !Relativistic case
 933  if (ncorespinor==2) then
 934    if (ex) then
 935      !Use <filepsp>.corewf.xml or <filepsp>.corewf.abinit
 936      call pawpsp_read_corewf(energy_cor,indlmn_cor,lcor,lmncmax,ncor,nphicor,pawrad(1),phi_cor,&
 937 &                            filename=filecore,kappacor=kappacor)
 938    else
 939      !Use default name
 940      call pawpsp_read_corewf(energy_cor,indlmn_cor,lcor,lmncmax,ncor,nphicor,pawrad(1),phi_cor,&
 941 &                            kappacor=kappacor)
 942    end if
 943 
 944 !Non-relativistic case
 945  else
 946    if (ex) then
 947      !Use <filepsp>.corewf.xml or <filepsp>.corewf.abinit
 948      call pawpsp_read_corewf(energy_cor,indlmn_cor,lcor,lmncmax,ncor,nphicor,pawrad(1),phi_cor,&
 949 &                            filename=filecore)
 950    else
 951      !Use default name
 952      call pawpsp_read_corewf(energy_cor,indlmn_cor,lcor,lmncmax,ncor,nphicor,pawrad(1),phi_cor)
 953    end if
 954    ABI_MALLOC(kappacor,(nphicor))
 955    kappacor(:)=zero
 956  endif
 957 
 958 !----------------------------------------------------------------------------------
 959 !2- Computation of phipphj=<phi_i|nabla|phi_core>
 960 !----------------------------------------------------------------------------------
 961 
 962  already_has_nabla=all(pawtab(:)%has_nabla==3)
 963  if (ncorespinor==2) then
 964    already_has_nabla=all(pawtab(:)%has_nabla==4)
 965 !  Should check whether this would work with spinor parallelism
 966    call pawnabla_core_init(mpsang,dtset%ntypat,pawrad,pawtab,phi_cor,indlmn_cor,diracflag=1)
 967  else
 968    call pawnabla_core_init(mpsang,dtset%ntypat,pawrad,pawtab,phi_cor,indlmn_cor)
 969  endif
 970 
 971 !Compute spin-orbit contributions if necessary
 972  use_spinorbit=(dtset%pawspnorb==1.and.dtset%userie/=111) ! For testing purpose
 973  if (use_spinorbit) then
 974    option_core=1
 975    call pawnabla_soc_init(phisocphj,option_core,dtset%ixc,mpi_enreg%my_natom,natom,&
 976 &       dtset%nspden,dtset%ntypat,pawang,pawrad,pawrhoij,pawtab,dtset%pawxcdev,&
 977 &       dtset%spnorbscl,dtset%typat,dtset%xc_denpos,dtset%xc_taupos,znucl,&
 978 &       phi_cor=phi_cor,indlmn_cor=indlmn_cor,&
 979 &       comm_atom=mpi_enreg%comm_atom,mpi_atmtab=mpi_enreg%my_atmtab)
 980  end if
 981 
 982 !----------------------------------------------------------------------------------
 983 !3- Opening of OPT2 file and header writing
 984 !----------------------------------------------------------------------------------
 985 
 986 !I/O mode is netCDF or Fortran
 987  iomode=merge(IO_MODE_ETSF,IO_MODE_FORTRAN_MASTER,dtset%iomode==IO_MODE_ETSF)
 988 #ifdef HAVE_NETCDF
 989  if (use_netcdf_forced) iomode=IO_MODE_ETSF
 990 #endif
 991 
 992  !(master proc only)
 993  if (i_am_master) then
 994 !  ====> NETCDF format
 995    if (iomode==IO_MODE_ETSF) then
 996      fformopt=611 
 997 #ifdef HAVE_NETCDF
 998 !    Open/create nc file
 999      NCF_CHECK(nctk_open_create(ncid,nctk_ncify(dtfil%fnameabo_app_opt2),xmpi_comm_self))
1000 !    Write header data
1001      NCF_CHECK(hdr%ncwrite(ncid,fformopt,nc_define=.true.))
1002 !    Define additional dimensions
1003      ncdims(1)%name="number_of_core_states"
1004      ncdims(1)%value=nphicor
1005      ncdims(2)%name="number_of_core_spinor_components"
1006      ncdims(2)%value=ncorespinor
1007      ncdims(3)%name="number_of_core_spins"
1008      ncdims(3)%value=3-ncorespinor
1009      NCF_CHECK(nctk_def_dims(ncid,ncdims))
1010 !    Define additional variables
1011      nctk_arrays(1)%name="eigenvalues_core"
1012      nctk_arrays(1)%dtype="dp"
1013      nctk_arrays(1)%shape_str="number_of_core_states"
1014      nctk_arrays(2)%name="dipole_core_valence"
1015      nctk_arrays(2)%dtype="dp"
1016      nctk_arrays(2)%shape_str=&
1017 &     "complex, number_of_cartesian_directions,number_of_core_states,"// &
1018 &     "number_of_atoms,max_number_of_states,number_of_kpoints,number_of_spins"
1019      nctk_arrays(3)%name="n_quantum_number_core"
1020      nctk_arrays(3)%dtype="int"
1021      nctk_arrays(3)%shape_str="number_of_core_states"
1022      nctk_arrays(4)%name="l_quantum_number_core"
1023      nctk_arrays(4)%dtype="int"
1024      nctk_arrays(4)%shape_str="number_of_core_states"
1025      nctk_arrays(5)%name="kappa_core"
1026      nctk_arrays(5)%dtype="int"
1027      nctk_arrays(5)%shape_str="number_of_core_states"
1028      NCF_CHECK(nctk_def_arrays(ncid, nctk_arrays))
1029      NCF_CHECK(nctk_set_atomic_units(ncid, "eigenvalues_core"))
1030      NCF_CHECK(nctk_set_atomic_units(ncid, "dipole_core_valence"))
1031 !    Write core states
1032      NCF_CHECK(nctk_set_datamode(ncid))
1033      varid=nctk_idname(ncid,"eigenvalues_core")
1034      NCF_CHECK(nf90_put_var(ncid,varid,energy_cor))
1035      varid=nctk_idname(ncid,"n_quantum_number_core")
1036      NCF_CHECK(nf90_put_var(ncid,varid,ncor))
1037      varid=nctk_idname(ncid,"l_quantum_number_core")
1038      NCF_CHECK(nf90_put_var(ncid,varid,lcor))
1039      varid=nctk_idname(ncid,"kappa_core")
1040      NCF_CHECK(nf90_put_var(ncid,varid,kappacor))
1041 !    Write eigenvalues
1042      varid=nctk_idname(ncid,"eigenvalues")
1043      NCF_CHECK(nf90_put_var(ncid,varid,reshape(eigen0,[mband,nkpt,nsppol])))
1044      !Close file here because the rest has possibly to be written with collective I/O
1045      NCF_CHECK(nf90_close(ncid))
1046 #else
1047      msg = "In order to use iomode=3 and prtnabla>0 together, NetCDF support must be enabled!"
1048      ABI_ERROR(msg)
1049 #endif
1050 !  ====> Standard FORTRAN binary file format
1051    else if (iomode==IO_MODE_FORTRAN_MASTER) then
1052      fformopt=612  ! MT 12sept21: change the OPT2 Fortran file format
1053      if (2*nphicor*natom*mband>2**30) fformopt=613 ! Format for large file records
1054      if (open_file(dtfil%fnameabo_app_opt2,msg,newunit=ount,form="unformatted",status="unknown")/= 0) then
1055        ABI_ERROR(msg)
1056      end if
1057      call hdr%fort_write(ount,fformopt,ierr,rewind=.true.)
1058      write(ount)(eigen0(jb),jb=1,mband*nkpt*nsppol)
1059      write(ount) nphicor
1060      do iln=1,nphicor
1061        write(ount) ncor(iln),lcor(iln),kappacor(iln),energy_cor(iln)
1062      end do
1063    else
1064      msg = "Wrong OPT2 file format!"
1065      ABI_BUG(msg)
1066    end if ! File format
1067  end if ! master node
1068  call xmpi_bcast(iomode,master,spaceComm_w,ierr)  ! Seems mandatory; why ?
1069  call xmpi_bcast(fformopt,master,spaceComm_w,ierr)
1070  iomode_etsf_mpiio=(iomode==IO_MODE_ETSF.and.nctk_has_mpiio.and.use_netcdf_mpiio)
1071 
1072  ABI_FREE(ncor)
1073  ABI_FREE(lcor)
1074  ABI_FREE(kappacor)
1075  ABI_FREE(phi_cor)
1076  ABI_FREE(energy_cor)
1077 
1078 !----------------------------------------------------------------------------------
1079 !4- Computation of <psi_n|p_i>(<phi_i|-i.nabla|phi_core>)
1080 !----------------------------------------------------------------------------------
1081 
1082 !Prepare core-valence dipoles writing
1083 !In case of netCDF access to OPT2 file, prepare collective I/O
1084  if (iomode == IO_MODE_ETSF) then
1085    if (iomode_etsf_mpiio) then
1086      if (i_am_master_spfft) then
1087        NCF_CHECK(nctk_open_modify(ncid,nctk_ncify(dtfil%fnameabo_app_opt2),spaceComm_band))
1088        varid=nctk_idname(ncid,"dipole_core_valence")
1089        if (xmpi_comm_size(spaceComm_w)>1) then
1090          NCF_CHECK(nctk_set_collective(ncid,varid))
1091        end if
1092        NCF_CHECK(nctk_set_datamode(ncid))
1093      end if
1094    else if (i_am_master) then
1095      NCF_CHECK(nctk_open_modify(ncid,nctk_ncify(dtfil%fnameabo_app_opt2),xmpi_comm_self))
1096      varid=nctk_idname(ncid,"dipole_core_valence")
1097      if (nctk_has_mpiio.and.(.not.use_netcdf_mpiio)) then
1098        NCF_CHECK(nctk_set_collective(ncid,varid))
1099      end if
1100      NCF_CHECK(nctk_set_datamode(ncid))
1101    end if     
1102  end if
1103  if (iomode_etsf_mpiio) then
1104    !If MPI-IO, store only elements for one band
1105    ABI_MALLOC(psinablapsi,(2,3,nphicor,natom,1))
1106    if (use_spinorbit) then
1107      ABI_MALLOC(psinablapsi_soc,(2,3,nphicor,natom,1))
1108    end if
1109  else
1110    !If not, store the elements for all bands
1111    ABI_MALLOC(psinablapsi,(2,3,nphicor,natom,mband))
1112    if (use_spinorbit) then
1113      ABI_MALLOC(psinablapsi_soc,(2,3,nphicor,natom,mband))
1114    end if
1115  end if
1116  pnp_size=size(psinablapsi)
1117  
1118 !Determine if cprj datastructure is distributed over bands
1119  mband_cprj=mcprj/(my_nspinor*mkmem*nsppol)
1120  cprj_paral_band=(mband_cprj<mband)
1121 
1122 !LOOP OVER SPINS
1123  ibg=0
1124  bdtot_index=0
1125  do isppol=1,nsppol
1126 
1127 !  LOOP OVER k POINTS
1128    do ikpt=1,nkpt
1129 
1130      etiq=ikpt+(isppol-1)*nkpt
1131      nband_k=dtset%nband(ikpt+(isppol-1)*nkpt)
1132      master_spfftband=minval(mpi_enreg%proc_distrb(ikpt,1:nband_k,isppol))
1133 
1134 !    Select k-points for current proc
1135      mykpt=.not.(proc_distrb_cycle(mpi_enreg%proc_distrb,ikpt,1,nband_k,isppol,mpi_enreg%me_kpt))
1136      if (mykpt) then
1137 
1138 !      Data depending on k-point
1139        istwf_k=dtset%istwfk(ikpt)
1140        cplex=2;if (istwf_k>1) cplex=1
1141 
1142 !      Extract cprj for this k-point
1143        nband_cprj_k=nband_k;if (cprj_paral_band) nband_cprj_k=nband_k/mpi_enreg%nproc_band
1144        if (mkmem*nsppol/=1) then
1145          iorder_cprj=0
1146          ABI_MALLOC(cprj_k_loc,(natom,my_nspinor*nband_cprj_k))
1147          call pawcprj_alloc(cprj_k_loc,0,dimcprj)
1148          call pawcprj_get(atindx1,cprj_k_loc,cprj,natom,1,ibg,ikpt,iorder_cprj,isppol,&
1149 &         mband_cprj,mkmem,natom,nband_cprj_k,nband_cprj_k,my_nspinor,nsppol,dtfil%unpaw,&
1150 &         mpicomm=mpi_enreg%comm_kpt,proc_distrb=mpi_enreg%proc_distrb)
1151        else
1152          cprj_k_loc => cprj
1153        end if
1154 
1155 !      if cprj are distributed over bands, gather them (because we need to mix bands)
1156        if (cprj_paral_band) then
1157          ABI_MALLOC(cprj_k,(natom,my_nspinor*nband_k))
1158          call pawcprj_alloc(cprj_k,0,dimcprj)
1159          call pawcprj_mpi_allgather(cprj_k_loc,cprj_k,natom,my_nspinor*nband_cprj_k, &
1160 &                                   my_nspinor*mpi_enreg%bandpp,&
1161 &         dimcprj,0,mpi_enreg%nproc_band,mpi_enreg%comm_band,ierr,rank_ordered=.false.)
1162        else
1163          cprj_k => cprj_k_loc
1164        end if
1165 
1166 !      Loops over bands
1167        do jb=1,nband_k
1168          !If MPI-IO, store only ib elements for each jb ; if not, store all (ib,jb) pairs
1169          my_jb=merge(1,jb,iomode_etsf_mpiio)
1170 
1171          psinablapsi(:,:,:,:,my_jb)=zero
1172          if (use_spinorbit) psinablapsi_soc(:,:,:,:,my_jb)=zero
1173 
1174 !        Computation of <psi_n|p_i><phi_i|-i.nabla|phi_core>
1175 !        ----------------------------------------------------------------------------------
1176 
1177 !        Select bands for current proc
1178          myband=.true.
1179          if (mpi_enreg%paral_kgb==1) then
1180            myband=(mod(jb-1,mpi_enreg%nproc_band)==mpi_enreg%me_band)
1181          else if (xmpi_paral==1) then
1182            myband=(abs(mpi_enreg%proc_distrb(ikpt,jb,isppol)-mpi_enreg%me_kpt)==0)
1183          end if
1184          if (myband) then
1185 
1186            jbsp=(jb-1)*my_nspinor
1187 
1188 !          1-spinor case
1189            if (dtset%nspinor==1.and.ncorespinor==1) then
1190              jbsp=jbsp+1
1191              if (cplex==1) then ! Real WF case
1192                do iatom=1,natom
1193                  itypat=dtset%typat(iatom)
1194                  lmn_size=pawtab(itypat)%lmn_size
1195                  do jlmn=1,lmn_size
1196                    do ilmn=1,lmncmax
1197                      ic=indlmn_cor(5,ilmn)
1198                      cpnm1=cprj_k(iatom,jbsp)%cp(1,jlmn)
1199                      psinablapsi(2,:,ic,iatom,my_jb)=psinablapsi(2,:,ic,iatom,my_jb) &
1200 &                        -cpnm1*pawtab(itypat)%nabla_ij(:,jlmn,ilmn)
1201                    end do !ilmn
1202                  end do !jlmn
1203                end do !iatom
1204              else ! Complex WF case
1205                do iatom=1,natom
1206                  itypat=dtset%typat(iatom)
1207                  lmn_size=pawtab(itypat)%lmn_size
1208                  do jlmn=1,lmn_size
1209                    do ilmn=1,lmncmax
1210                      ic=indlmn_cor(5,ilmn)
1211                      cpnm1=cprj_k(iatom,jbsp)%cp(1,jlmn)
1212                      cpnm2=cprj_k(iatom,jbsp)%cp(2,jlmn)
1213                      psinablapsi(1,:,ic,iatom,my_jb)=psinablapsi(1,:,ic,iatom,my_jb) &
1214 &                        -cpnm2*pawtab(itypat)%nabla_ij(:,jlmn,ilmn)
1215                      psinablapsi(2,:,ic,iatom,my_jb)=psinablapsi(2,:,ic,iatom,my_jb) &
1216 &                        -cpnm1*pawtab(itypat)%nabla_ij(:,jlmn,ilmn)
1217                    end do !ilmn
1218                  end do !jlmn
1219                end do !iatom
1220              end if
1221 
1222 !          2-spinor case
1223            else if (dtset%nspinor==2.and.ncorespinor==2) then
1224              do ispinor=1,my_nspinor
1225                jbsp=jbsp+1
1226                do iatom=1,natom
1227                  itypat=dtset%typat(iatom)
1228                  lmn_size=pawtab(itypat)%lmn_size
1229                  do jlmn=1,lmn_size
1230                    do ilmn=1,lmncmax
1231                      is=indlmn_cor(6,ilmn)
1232                      if (modulo(jbsp,2)==modulo(is,2)) then ! Nabla is a spin-diagonal operator
1233                        ic=indlmn_cor(5,ilmn)
1234                        if (ic>0) then
1235                          cpnm1=cprj_k(iatom,jbsp)%cp(1,jlmn)
1236                          cpnm2=cprj_k(iatom,jbsp)%cp(2,jlmn)
1237                          psinablapsi(1,:,ic,iatom,my_jb)=psinablapsi(1,:,ic,iatom,my_jb) &
1238 &                            +cpnm1*pawtab(itypat)%nabla_im_ij(:,jlmn,ilmn) &
1239 &                            -cpnm2*pawtab(itypat)%nabla_ij(:,jlmn,ilmn)
1240                          psinablapsi(2,:,ic,iatom,my_jb)=psinablapsi(2,:,ic,iatom,my_jb) &
1241 &                            -cpnm1*pawtab(itypat)%nabla_ij(:,jlmn,ilmn) &
1242 &                            -cpnm2*pawtab(itypat)%nabla_im_ij(:,jlmn,ilmn)
1243                        end if
1244                      end if
1245                    end do ! ilmn
1246                  end do !jlmn
1247                end do !iatom
1248              end do !ispinor
1249            else
1250              msg="Core and valence WF should have the same spinor representation!"
1251              ABI_BUG(msg)
1252              !N. Brouwer initial coding: should be justified!
1253              !if (dtset%nspinor==1.and.ncorespinor==2) then  ! Average core spinors
1254              !  psinablapsi(1,:,ic,iatom,my_jb)=psinablapsi(1,:,ic,iatom,my_jb) &
1255              ! &    +half_sqrt2*(cpnm1*pawtab(itypat)%nabla_im_ij(:,jlmn,ilmn) &
1256              ! &                +cpnm2*pawtab(itypat)%nabla_ij(:,jlmn,ilmn))
1257              !  psinablapsi(2,:,ic,iatom,my_jb)=psinablapsi(2,:,ic,iatom,my_jb) &
1258              ! &    +half_sqrt2*(cpnm2*pawtab(itypat)%nabla_im_ij(:,jlmn,ilmn) &
1259              ! &                -cpnm1*pawtab(itypat)%nabla_ij(:,jlmn,ilmn))
1260              !else if (dtset%nspinor==2.and.ncorespinor==1) then ! Average valence spinors
1261              !  psinablapsi(1,:,ic,iatom,my_jb)=psinablapsi(1,:,ic,iatom,my_jb) &
1262              ! &    +half_sqrt2*cpnm2*pawtab(itypat)%nabla_ij(:,jlmn,ilmn)
1263              !  psinablapsi(2,:,ic,iatom,my_jb)=psinablapsi(2,:,ic,iatom,my_jb) &
1264              ! &    -half_sqrt2*cpnm1*pawtab(itypat)%nabla_ij(:,jlmn,ilmn)
1265              !endif
1266            endif
1267 
1268 !          Spin-orbit coupling contribution:
1269 !             Sum_i,ss'[<psi^s_n|p_i><phi_i|1/4 Alpha^2 (Sigma^ss' X dV/dr)|phj_core^s'>]
1270            if (use_spinorbit) then
1271 !            Add: Sum_i,ss'[<Psi^s_n|p_i> (Sigma^ss' X g_ij_core^s']
1272 !             where: g_ij_core^s = <Phi_i| 1/4 Alpha^2 dV/dr vec(r)/r) |Phj_core^s>
1273 !            Note that:
1274 !             if phi_cor_jlmn_cor(:) is up:
1275 !              phisocphj(:)%value(re:im,1,idir,ilmn,jlmn_cor) is (Sigma^up-up X g_ij_core^up)
1276 !              phisocphj(:)%value(re:im,2,idir,ilmn,jlmn_cor) is (Sigma^dn-up X g_ij_core^up)
1277 !             if phi_cor_jlmn_cor(:) is down:
1278 !              phisocphj(:)%value(re:im,1,idir,ilmn,jlmn_cor) is (Sigma^up-dn X g_ij_core^dn)
1279 !              phisocphj(:)%value(re:im,2,idir,ilmn,jlmn_cor) is (Sigma^dn-dn X g_ij_core^dn)
1280 !            Not compatible with parallelization over spinors
1281              jbsp=1+(jb-1)*dtset%nspinor
1282              do iatom=1,natom
1283                itypat=dtset%typat(iatom)
1284                lmn_size=pawtab(itypat)%lmn_size
1285                do jlmn=1,lmn_size
1286                  do ilmn=1,lmncmax
1287                    ic=indlmn_cor(5,ilmn)
1288                    if (ic>0) then
1289                      soc_ij => phisocphj(iatom)%value(:,:,:,jlmn,ilmn)
1290                      !Contribution from real part of <Psi^s_n|p_i>
1291                      cpnm1=cprj_k(iatom,jbsp  )%cp(1,jlmn)
1292                      cpnm2=cprj_k(iatom,jbsp+1)%cp(1,jlmn)
1293                      do idir=1,3
1294                        psinablapsi_soc(1,idir,ic,iatom,my_jb)=psinablapsi_soc(1,idir,ic,iatom,my_jb) &
1295 &                             +soc_ij(1,1,idir)*cpnm1+soc_ij(1,2,idir)*cpnm2
1296                        psinablapsi_soc(2,idir,ic,iatom,my_jb)=psinablapsi_soc(2,idir,ic,iatom,my_jb) &
1297 &                             +soc_ij(2,1,idir)*cpnm1+soc_ij(2,2,idir)*cpnm2
1298                      end do
1299                      !Contribution from imaginary part of <Psi^s_n|p_i>
1300                      cpnm1=cprj_k(iatom,jbsp  )%cp(2,jlmn)
1301                      cpnm2=cprj_k(iatom,jbsp+1)%cp(2,jlmn)
1302                      do idir=1,3
1303                        psinablapsi_soc(1,idir,ic,iatom,my_jb)=psinablapsi_soc(1,idir,ic,iatom,my_jb) &
1304 &                             +soc_ij(2,1,idir)*cpnm1+soc_ij(2,2,idir)*cpnm2
1305                        psinablapsi_soc(2,idir,ic,iatom,my_jb)=psinablapsi_soc(2,idir,ic,iatom,my_jb) &
1306 &                             -soc_ij(1,1,idir)*cpnm1-soc_ij(1,2,idir)*cpnm2
1307                      end do
1308                    end if
1309                  end do ! ilmn
1310                end do ! jlmn
1311              end do ! iatom
1312            end if ! use_spinorbit
1313 
1314            if (iomode_etsf_mpiio.and.mpi_enreg%paral_spinor==1) then
1315              call timab(48,1,tsec)
1316              call xmpi_sum_master(psinablapsi,master,spaceComm_spinor,ierr)
1317              call timab(48,2,tsec)
1318            end if
1319 
1320          end if ! myband
1321 
1322 !        Write to OPT2 file in case of MPI-IO
1323          if (iomode_etsf_mpiio.and.i_am_master_spfft) then
1324            nc_start=[1,1,1,1,jb,ikpt,isppol];nc_stride=[1,1,1,1,1,1,1] 
1325            if (myband) then
1326              if (use_spinorbit) psinablapsi=psinablapsi+psinablapsi_soc
1327              nc_count=[2,3,nphicor,natom,1,1,1]
1328            else
1329              nc_count=[0,0,0,0,0,0,0]
1330            end if
1331 #ifdef HAVE_NETCDF
1332            NCF_CHECK(nf90_put_var(ncid,varid,psinablapsi,start=nc_start,stride=nc_stride,count=nc_count))
1333 #endif
1334          end if
1335 
1336        end do ! jb
1337        
1338        if (mkmem/=0) then
1339          ibg = ibg +  my_nspinor*nband_cprj_k
1340        end if
1341 
1342        if (cprj_paral_band) then
1343          call pawcprj_free(cprj_k)
1344          ABI_FREE(cprj_k)
1345        end if
1346        if (mkmem*nsppol/=1) then
1347          call pawcprj_free(cprj_k_loc)
1348          ABI_FREE(cprj_k_loc)
1349        end if
1350 
1351 !      Write to OPT2 file if not MPI-IO
1352 
1353 !      >>> Reduction in case of parallelism
1354        if (.not.iomode_etsf_mpiio) then
1355          call timab(48,1,tsec)
1356          call xmpi_sum_master(psinablapsi,master,spaceComm_bandspinor,ierr)
1357          call timab(48,2,tsec)
1358          if (use_spinorbit) then
1359            call xmpi_sum_master(psinablapsi_soc,master,spaceComm_band,ierr)
1360            psinablapsi=psinablapsi+psinablapsi_soc
1361          end if
1362        end if
1363 
1364 !      >>> This my kpt and I am the master node: I write the data    
1365        if (.not.iomode_etsf_mpiio) then
1366          if (i_am_master) then
1367            if (iomode==IO_MODE_ETSF) then
1368              nc_start=[1,1,1,1,1,ikpt,isppol];nc_stride=[1,1,1,1,1,1,1] 
1369              nc_count=[2,3,nphicor,natom,mband,1,1]
1370 #ifdef HAVE_NETCDF
1371              NCF_CHECK(nf90_put_var(ncid,varid,psinablapsi,start=nc_start,stride=nc_stride,count=nc_count))
1372 #endif
1373            else
1374              if (fformopt==612) then ! New OPT2 file format
1375                write(ount) (((psinablapsi(1:2,1,ic,iatom,jb),ic=1,nphicor),iatom=1,natom),jb=1,nband_k)
1376                write(ount) (((psinablapsi(1:2,2,ic,iatom,jb),ic=1,nphicor),iatom=1,natom),jb=1,nband_k)
1377                write(ount) (((psinablapsi(1:2,3,ic,iatom,jb),ic=1,nphicor),iatom=1,natom),jb=1,nband_k)
1378              else if (fformopt==613) then ! Large OPT2 file format
1379                do jb=1,nband_k
1380                  write(ount) ((psinablapsi(1:2,1,ic,iatom,jb),ic=1,nphicor),iatom=1,natom)
1381                  write(ount) ((psinablapsi(1:2,2,ic,iatom,jb),ic=1,nphicor),iatom=1,natom)
1382                  write(ount) ((psinablapsi(1:2,3,ic,iatom,jb),ic=1,nphicor),iatom=1,natom)
1383                end do
1384              else ! Old OPT2 file format
1385                !The old writing was not efficient (indexes order is bad)
1386                do iatom=1,natom
1387                  write(ount) ((psinablapsi(1:2,1,ic,iatom,jb),jb=1,nband_k),ic=1,nphicor)
1388                  write(ount) ((psinablapsi(1:2,2,ic,iatom,jb),jb=1,nband_k),ic=1,nphicor)
1389                  write(ount) ((psinablapsi(1:2,3,ic,iatom,jb),jb=1,nband_k),ic=1,nphicor)
1390                end do
1391              end if
1392            end if
1393 
1394 !        >>> This my kpt and I am not the master node: I send the data    
1395          else if (i_am_master_band.and.i_am_master_spfft) then
1396            if (mpi_enreg%me_kpt/=master_spfftband) then
1397              ABI_BUG('Problem with band communicator!')
1398            end if
1399            call xmpi_exch(psinablapsi,pnp_size,mpi_enreg%me_kpt,psinablapsi,master,spaceComm_kpt,etiq,ierr)
1400          end if
1401        end if  
1402 
1403 !    >>> This is not my kpt and I am the master node: I receive the data and I write    
1404      elseif ((.not.iomode_etsf_mpiio).and.i_am_master) then ! mykpt
1405        sender=master_spfftband
1406        call xmpi_exch(psinablapsi,pnp_size,sender,psinablapsi,master,spaceComm_kpt,etiq,ierr)
1407        if (iomode==IO_MODE_ETSF) then
1408          nc_start=[1,1,1,1,1,ikpt,isppol];nc_stride=[1,1,1,1,1,1,1] 
1409          nc_count=[2,3,nphicor,natom,mband,1,1]
1410 #ifdef HAVE_NETCDF
1411          NCF_CHECK(nf90_put_var(ncid,varid,psinablapsi,start=nc_start,stride=nc_stride,count=nc_count))
1412 #endif
1413        else
1414          if (fformopt==612) then ! New OPT2 file format
1415            write(ount) (((psinablapsi(1:2,1,ic,iatom,jb),ic=1,nphicor),iatom=1,natom),jb=1,nband_k)
1416            write(ount) (((psinablapsi(1:2,2,ic,iatom,jb),ic=1,nphicor),iatom=1,natom),jb=1,nband_k)
1417            write(ount) (((psinablapsi(1:2,3,ic,iatom,jb),ic=1,nphicor),iatom=1,natom),jb=1,nband_k)
1418          else if (fformopt==613) then ! Large OPT2 file format
1419            do jb=1,nband_k
1420              write(ount) ((psinablapsi(1:2,1,ic,iatom,jb),ic=1,nphicor),iatom=1,natom)
1421              write(ount) ((psinablapsi(1:2,2,ic,iatom,jb),ic=1,nphicor),iatom=1,natom)
1422              write(ount) ((psinablapsi(1:2,3,ic,iatom,jb),ic=1,nphicor),iatom=1,natom)
1423            end do
1424          else ! Old OPT2 file format
1425            !The old writing was not efficient (indexes order is bad)
1426            do iatom=1,natom
1427              write(ount) ((psinablapsi(1:2,1,ic,iatom,jb),jb=1,nband_k),ic=1,nphicor)
1428              write(ount) ((psinablapsi(1:2,2,ic,iatom,jb),jb=1,nband_k),ic=1,nphicor)
1429              write(ount) ((psinablapsi(1:2,3,ic,iatom,jb),jb=1,nband_k),ic=1,nphicor)
1430            end do
1431          end if
1432        end if
1433      end if ! mykpt
1434 
1435      bdtot_index=bdtot_index+nband_k
1436 
1437 !    End loop on spin,kpt
1438    end do ! ikpt
1439  end do !isppol
1440 
1441 !Close file
1442  if (i_am_master.or.(iomode_etsf_mpiio.and.i_am_master_spfft)) then
1443    if (iomode==IO_MODE_ETSF) then
1444 #ifdef HAVE_NETCDF
1445      NCF_CHECK(nf90_close(ncid))
1446 #endif
1447    else
1448      ierr=close_unit(ount,msg)
1449      ABI_CHECK(ierr==0,"Error while closing OPT2 file")
1450    end if
1451  end if
1452 
1453 !Datastructures deallocations
1454  ABI_FREE(indlmn_cor)
1455  ABI_FREE(psinablapsi)
1456  if (use_spinorbit) then
1457    ABI_FREE(psinablapsi_soc)
1458    do iatom=1,natom
1459      ABI_FREE(phisocphj(iatom)%value)
1460    end do
1461    ABI_FREE(phisocphj)
1462  end if
1463  if (.not.already_has_nabla) then
1464    do itypat=1,dtset%ntypat
1465      if (allocated(pawtab(itypat)%nabla_ij)) then
1466        ABI_FREE(pawtab(itypat)%nabla_ij)
1467        pawtab(itypat)%has_nabla=0
1468      end if
1469      if (allocated(pawtab(itypat)%nabla_im_ij)) then
1470        ABI_FREE(pawtab(itypat)%nabla_im_ij)
1471      end if
1472    end do
1473  end if
1474 
1475  DBG_EXIT("COLL")
1476 
1477  end subroutine optics_paw_core

m_paw_optics/pawnabla_soc_init [ Functions ]

[ Top ] [ m_paw_optics ] [ Functions ]

NAME

 pawnabla_soc_init

FUNCTION

 Compute the PAW SOC contribution(s) to the momentum PAW matrix elements,
  i.e. <Phi_i|1/4 Alpha^2 dV/dr (Sigma X vec(r)/r) |Phi_j>
   where:
    {Phi_i}= AE partial waves
    Alpha = inverse of fine structure constant
    Sigma^alpha,beta= Pauli matrices
    X = cross product

 There are 2 typical uses:
   - Valence-valence terms: Phi_i and Phi_j are PAW AE partial waves (unpolarized)
   - Core-valence terms: Phi_i is are AE partial waves and Phi_j are core AE wave-functions (spinors)

 In practice we compute:
  (Sigma^up-up X g_ij) and (Sigma^up-dn X g_ij)    (X = vector cross product)
  (Sigma^dn-up X g_ij) and (Sigma^dn-dn X g_ij)
   where:
    g_ij= 1/4 Alpha^2 Int_[Phi_i(r)/r Phi_j(r)/r dV(r)/dr r^2 dr] . Gvec_ij
        and Gvec_ij= Int[S_limi S_ljmj vec(r)/r dOmega] (Gaunt coefficients)

COPYRIGHT

 Copyright (C) 2021-2024 ABINIT group (NBrouwer,MT)
 This file is distributed under the terms of the
 GNU General Public License, see ~ABINIT/COPYING
 or http://www.gnu.org/copyleft/gpl.txt .

INPUTS

  ixc= choice of exchange-correlation scheme (see above, and below)
  my_natom=number of atoms treated by current processor
  natom=total number of atoms in cell
  nspden=number of spin-density components
  ntypat=number of types of atoms in unit cell.
  option_core=Type of calculation: 0=valence-valence, 1=core-valence
  pawang <type(pawang_type)>=paw angular mesh and related data
  pawrad(ntypat) <type(pawrad_type)>=paw radial mesh and related data
  pawrhoij(my_natom) <type(pawrhoij_type)>= paw rhoij occupancies and related data
  pawtab(ntypat) <type(pawtab_type)>=paw tabulated starting data
  pawxcdev=Choice of XC development (0=no dev. (use of angular mesh) ; 1 or 2=dev. on moments)
  spnorbscl=scaling factor for spin-orbit coupling
  typat(natom) =Type of each atoms
  xc_denpos= lowest allowed density (usually for the computation of the XC functionals)
  xc_taupos= lowest allowed kinetic energy density (for mGGA XC functionals)
  znucl(ntypat)=gives the nuclear charge for all types of atoms
  [phi_cor(mesh_size,nphicor)]=--optional-- core wave-functions for the current type of atoms;
                               only needed when option_core=1
  [indlmn_cor(6,nlmn_core)]=--optional-- array giving l,m,n,lm,ln,s for i=lmn, for the core wave functions;
                            only needed when option_core=1
  [mpi_atmtab(:)]=--optional-- indexes of the atoms treated by current proc
  [comm_atom]=--optional-- MPI communicator over atoms

OUTPUT

     phisocphj(iat)%value(1,1,idir,ilmn,jlmn) is real part of (Sigma^up-up X g_ij)
     phisocphj(iat)%value(2,1,idir,ilmn,jlmn) is imaginary part of (Sigma^up-up X g_ij)
     phisocphj(iat)%value(1,2,idir,ilmn,jlmn) is real part of (Sigma^up-dn X g_ij)
     phisocphj(iat)%value(2,2,idir,ilmn,jlmn) is imaginary part of (Sigma^up-dn X g_ij)
   If option_core==1 and nspinor_cor==2 (core-valence with spinorial core WF):
     phisocphj(iat)%value(1,1,idir,ilmn,2*jlmn-1) is real part of (Sigma^up-up X g_ij^up)
     phisocphj(iat)%value(2,1,idir,ilmn,2*jlmn-1) is imaginary part of (Sigma^up-up X g_ij^up)
     phisocphj(iat)%value(1,2,idir,ilmn,2*jlmn-1) is real part of (Sigma^dn-up X g_ij^dn)
     phisocphj(iat)%value(2,2,idir,ilmn,2*jlmn-1) is imaginary part of (Sigma^dn-up X g_ij^dn)
     phisocphj(iat)%value(1,1,idir,ilmn,2*jlmn  ) is real part of (Sigma^up-dn X g_ij^up)
     phisocphj(iat)%value(2,1,idir,ilmn,2*jlmn  ) is imaginary part of (Sigma^up-dn X g_ij^up)
     phisocphj(iat)%value(1,2,idir,ilmn,2*jlmn  ) is real part of (Sigma^dn-dn X g_ij^dn)
     phisocphj(iat)%value(2,2,idir,ilmn,2*jlmn  ) is imaginary part of (Sigma^dn-dn X g_ij^dn)
 (idir=cartesian direction)

SIDE EFFECTS

NOTES

 If Phi_j is not polarized,
    (Sigma^dn-dn X g_ij)=-(Sigma^up-up X g_ij)
    (Sigma^dn-up X g_ij)= (Sigma^up-dn X g_ij)^*
    So, we store only 2 components.
 If Phi_j is polarized, the spin component is included in the last dimension of
   phisocphj(iat)%value, i.e. lmn_size_cor=2*lmn_size

SOURCE

1840  subroutine pawnabla_soc_init(phisocphj,option_core,ixc,my_natom,natom,nspden,ntypat,pawang, &
1841 &           pawrad,pawrhoij,pawtab,pawxcdev,spnorbscl,typat,xc_denpos,xc_taupos,znucl, &
1842 &           phi_cor,indlmn_cor,mpi_atmtab,comm_atom) ! Optional arguments
1843 
1844 !Arguments ------------------------------------
1845 !scalars
1846  integer,intent(in) :: ixc,my_natom,natom,nspden,ntypat,option_core,pawxcdev
1847  integer,optional,intent(in) :: comm_atom
1848  real(dp),intent(in) :: spnorbscl,xc_denpos,xc_taupos
1849  type(pawang_type),intent(in) :: pawang
1850 !arrays
1851  integer,intent(in),target,optional :: indlmn_cor(:,:)
1852  integer,intent(in) :: typat(natom)
1853  integer,optional,target,intent(in) :: mpi_atmtab(:)
1854  real(dp),intent(in),target,optional :: phi_cor(:,:)
1855  real(dp),intent(in) :: znucl(ntypat)
1856  type(coeff5_type),allocatable,target,intent(inout) :: phisocphj(:)
1857  type(pawrad_type),target,intent(in) :: pawrad(ntypat)
1858  type(pawrhoij_type),intent(inout) :: pawrhoij(my_natom)
1859  type(pawtab_type),target,intent(in) :: pawtab(ntypat)
1860 
1861 !Local variables-------------------------------
1862 !scalars
1863  real(dp),parameter :: one_over_fourpi   = one/sqrt(four_pi)
1864  real(dp),parameter :: sqr_fourpi_over_3 = sqrt(four_pi/3)
1865  real(dp),parameter :: QuarterFineStruct2=(half/InvFineStruct)**2
1866  real(dp),parameter :: hyb_mixing_ = 0.0_dp   ! Fake value to be updated in the future
1867  integer :: iatom,iatom_tot,itypat,ii,jj,ierr,ipts,ignt,sgnkappa
1868  integer :: idum,option,usenhat,usekden,usecore,xclevel,nkxc,my_comm_atom
1869  integer :: mesh_size,mesh_size_cor,lmn_size,lmn2_size,lmn_size_j,lmn_size_cor
1870  integer :: lm_size,ln_size,ln_size_j,ln_size_cor,nspinor_cor
1871  integer :: ilmn,ilm,iln,jl,jm,jm_re,jm_im,jlmn,jlm,jlm_re,jlm_im,jln,js,klm_re,klm_im
1872  logical :: my_atmtab_allocated,paral_atom
1873  real(dp) :: avg,cgc,compch_sph_dum,eexc_dum,eexcdc_dum,jmj
1874  real(dp) :: fact_re,fact_im,gx_re,gx_im,gy_re,gy_im,gz_re,gz_im,if3
1875  character(len=500) :: msg
1876 !arrays
1877  integer,pointer :: my_atmtab(:),indlmn(:,:),indlmn_j(:,:)
1878  logical,allocatable :: lmselect(:)
1879  real(dp) :: nhat_dum(1,1,1),trho_dum(1,1,1),kxc_dum(1,1,1),k3xc_dum(1,1,1)
1880  real(dp),allocatable :: rho1(:,:,:),tau1(:,:,:),rhosph(:),vhartree(:),vxc(:,:,:)
1881  real(dp),allocatable :: intf3(:,:),potsph(:),dVdr(:),func(:)
1882  real(dp),pointer :: phi_j(:,:),soc_ij(:,:,:,:,:)
1883  type(pawrad_type),pointer :: pawrd
1884  type(pawtab_type),pointer :: pawtb
1885 
1886 ! ************************************************************************
1887 
1888 !Some checks in case of core-valence (option_core=1)
1889  if (option_core/=0.and.option_core/=1) then
1890    msg='Wrong option_core value!'
1891    ABI_BUG(msg)
1892  end if
1893  if (option_core==1) then
1894 !  Check if we have the optional arguments
1895    if ((.not.present(phi_cor)).or.(.not.present(indlmn_cor))) then
1896      msg='For core-valence calculation, need phi_cor and indlmn_cor!'
1897      ABI_BUG(msg)
1898    end if
1899 !  Check if we have relativistic core wave functions
1900    if (size(indlmn_cor,1)<8) then
1901      write(msg,'(a)') 'Wrong 1st dim. of indlmn_cor in pawnabla_soc_init (need spinors)!'
1902      ABI_BUG(msg)
1903    end if
1904  endif
1905 
1906 !Some useful variables
1907  usekden=pawxc_get_usekden(ixc)
1908  usecore=1 ; nkxc=0 ; usenhat=0
1909  xclevel=pawxc_get_xclevel(ixc)
1910  if (option_core==1) then
1911    mesh_size_cor=size(phi_cor,1)
1912    lmn_size_cor=size(indlmn_cor,2) !Includes spinors
1913    ln_size_cor=size(phi_cor,2)
1914    nspinor_cor=maxval(indlmn_cor(6,1:lmn_size_cor))
1915  end if
1916 
1917 !Prepare output arrays
1918  if (allocated(phisocphj)) then
1919    do iatom=1,natom
1920       if (allocated(phisocphj(iatom)%value)) then
1921         ABI_FREE(phisocphj(iatom)%value)
1922       end if
1923    end do
1924    ABI_FREE(phisocphj)
1925  end if
1926  ABI_MALLOC(phisocphj,(natom))
1927  do iatom=1,natom
1928    lmn_size=pawtab(typat(iatom))%lmn_size
1929    if (option_core==0) then
1930      ABI_MALLOC(phisocphj(iatom)%value,(2,2,3,lmn_size,lmn_size))
1931    else
1932      !lmn_size_cor is double because it contains the spin component
1933      ABI_MALLOC(phisocphj(iatom)%value,(2,2,3,lmn_size,lmn_size_cor))
1934    end if
1935    phisocphj(iatom)%value=zero
1936  end do
1937 
1938 !Set up parallelism over atoms
1939  paral_atom=(present(comm_atom).and.(my_natom/=natom))
1940  nullify(my_atmtab);if (present(mpi_atmtab)) my_atmtab => mpi_atmtab
1941  my_comm_atom=xmpi_comm_self;if (present(comm_atom)) my_comm_atom=comm_atom
1942  call get_my_atmtab(my_comm_atom,my_atmtab,my_atmtab_allocated,paral_atom,natom,&
1943 &                   my_natom_ref=my_natom)
1944 
1945 !-------------------------------------------------------------------
1946 !Loop over atoms
1947 
1948  do iatom=1,my_natom
1949 
1950 !  Atom-dependent data
1951    itypat=typat(iatom)
1952    pawrd => pawrad(itypat)
1953    pawtb  => pawtab(itypat)
1954    lmn_size=pawtb%lmn_size
1955    lmn2_size=pawtb%lmn2_size
1956    lm_size=pawtb%lcut_size**2
1957    ln_size=pawtb%basis_size
1958    mesh_size=pawtb%mesh_size
1959    indlmn => pawtb%indlmn
1960    ABI_MALLOC(lmselect,(lm_size))
1961    lmselect(:)=.true.
1962 
1963 !  Distinguish valence-valence and core-valence cases
1964    if (option_core==0) then
1965      ln_size_j=ln_size
1966      lmn_size_j=lmn_size
1967      indlmn_j => pawtb%indlmn
1968      phi_j => pawtb%phi
1969    else
1970      ln_size_j=ln_size_cor
1971      lmn_size_j=lmn_size_cor
1972      indlmn_j => indlmn_cor
1973      phi_j => phi_cor
1974      if (mesh_size_cor<mesh_size) then
1975        msg='mesh_size and mesh_size_cor not compatible!'
1976        ABI_BUG(msg)
1977      end if
1978    endif
1979 
1980 !  Manage parallelism
1981    iatom_tot=iatom;if (paral_atom) iatom_tot=my_atmtab(iatom)
1982    soc_ij => phisocphj(iatom_tot)%value(:,:,:,:,:)
1983 
1984 !-------------------------------------------------------------------
1985 !Compute all-electron density
1986 
1987    ABI_MALLOC(rho1,(mesh_size,lm_size,nspden))
1988    option=2 ; rho1=zero
1989    call pawdensities(compch_sph_dum,1,iatom_tot,lmselect,lmselect,lm_size,&
1990 &       nhat_dum,nspden,-1,0,option,-1,0,pawang,0,pawrd,&
1991 &       pawrhoij(iatom),pawtb,rho1,trho_dum)
1992    if (usekden==1) then
1993      ABI_MALLOC(tau1,(mesh_size,lm_size,nspden))
1994      tau1=zero
1995      call pawkindensities(1,lmselect,lm_size,nspden,-1,option,-1,&
1996 &         pawang,pawrd,pawrhoij(iatom),pawtb,tau1,trho_dum)
1997    end if
1998 
1999 !-------------------------------------------------------------------
2000 !Compute spherical potential and compute its first derivative dV/dr
2001 
2002    ABI_MALLOC(potsph,(mesh_size))
2003    ABI_MALLOC(dVdr,(mesh_size))
2004    potsph=zero ; dVdr=zero
2005 
2006 !  Compute XC potential
2007    option=1
2008    if (pawxcdev/=0) then
2009      ABI_MALLOC(vxc,(mesh_size,lm_size,nspden))
2010      vxc=zero
2011      call pawxcm(pawtb%coredens,eexc_dum,eexcdc_dum,idum,hyb_mixing_,ixc,kxc_dum,lm_size,&
2012 &         lmselect,nhat_dum,nkxc,.false.,mesh_size,nspden,option,pawang,pawrd,&
2013 &         pawxcdev,rho1,usecore,usenhat,vxc,xclevel,xc_denpos)
2014      potsph(1:mesh_size)=half*(vxc(1:mesh_size,1,1)+vxc(1:mesh_size,1,nspden))
2015    else
2016      ABI_MALLOC(vxc,(mesh_size,pawang%angl_size,nspden))
2017      vxc=zero
2018      call pawxc(pawtb%coredens,eexc_dum,eexcdc_dum,hyb_mixing_,ixc,kxc_dum,k3xc_dum,&
2019 &         lm_size,lmselect,nhat_dum,nkxc,nkxc,.false.,mesh_size,nspden,option,pawang,&
2020 &         pawrd,rho1,usecore,usenhat,vxc,xclevel,xc_denpos,&
2021 &         coretau=pawtb%coretau,taur=tau1,xc_taupos=xc_taupos)
2022      potsph(1:mesh_size)=zero
2023      do ipts=1,pawang%angl_size
2024        potsph(1:mesh_size)=potsph(1:mesh_size) &
2025 &        +half*(vxc(1:mesh_size,ipts,1)+vxc(1:mesh_size,ipts,nspden))*pawang%angwgth(ipts)
2026      end do
2027      potsph(1:mesh_size)=sqrt(four_pi)*potsph(1:mesh_size)
2028    end if
2029 
2030 !  Compute Hartree potentialHalfFineStruct2
2031    ABI_MALLOC(vhartree,(mesh_size))
2032    ABI_MALLOC(rhosph,(mesh_size))
2033    vhartree=zero ; rhosph=zero
2034    rhosph(1:mesh_size)=rho1(1:mesh_size,1,1)
2035    if (usecore==1) rhosph(1:mesh_size)=rhosph(1:mesh_size)+sqrt(four_pi)*pawtb%coredens(1:mesh_size)
2036    rhosph(1:mesh_size)=rhosph(1:mesh_size)*four_pi*pawrd%rad(1:mesh_size)**2
2037    call poisson(rhosph,0,pawrd,vhartree)
2038    vhartree(2:mesh_size)=(vhartree(2:mesh_size)-sqrt(four_pi)*znucl(itypat))/pawrd%rad(2:mesh_size)
2039    call pawrad_deducer0(vhartree,mesh_size,pawrd)
2040    potsph(1:mesh_size)=potsph(1:mesh_size)+vhartree(1:mesh_size)
2041 
2042 !  Apply angular scaling factor
2043    potsph(1:mesh_size)=one_over_fourpi*potsph(1:mesh_size)
2044 
2045 !  Compute 1st derivative of potential
2046    call nderiv_gen(dVdr,potsph,pawrd)
2047 
2048 !  Multiply by relativistic factor
2049    dVdr(1:mesh_size)=dVdr(1:mesh_size)*(one/(one-potsph(1:mesh_size)*half/InvFineStruct**2)**2)
2050 
2051    ABI_FREE(vxc)
2052    ABI_FREE(vhartree)
2053    ABI_FREE(potsph)
2054    ABI_FREE(rhosph)
2055    ABI_FREE(lmselect)
2056    ABI_FREE(rho1)
2057    if (usekden==1) then
2058      ABI_FREE(tau1)
2059    end if
2060 
2061 !-------------------------------------------------------------------
2062 !Compute radial and angular contributions
2063 
2064    ABI_MALLOC(intf3,(ln_size,ln_size_j))
2065    intf3=zero
2066 
2067 !  >>>> Calculate f_3= alpha^2/4 int[dr ui*(r) uj(r) dV/dr]
2068    ABI_MALLOC(func,(mesh_size))
2069    do jln=1,ln_size_j
2070      do iln=1,ln_size
2071        func(1:mesh_size)=dVdr(1:mesh_size)*pawtb%phi(1:mesh_size,iln)*phi_j(1:mesh_size,jln)
2072        call simp_gen(intf3(iln,jln),func,pawrd)
2073      end do
2074    end do
2075    intf3(:,:)=QuarterFineStruct2*spnorbscl*intf3(:,:)
2076    ABI_FREE(func)
2077 
2078 !  Loop over initial states (valence or core, according to option_core)
2079    do jlmn=1,lmn_size_j
2080      jl=indlmn_j(1,jlmn)
2081      jm=indlmn_j(2,jlmn)
2082      jlm=indlmn_j(4,jlmn)
2083      jln=indlmn_j(5,jlmn)
2084 
2085 !    In case of spinorial core wave function, we have to handle imaginary
2086 !      spherical harmonics as linear combination of real spherical harmonics
2087 !    See Brouwer et al, CPC 266, 108029 (2021), equation (21)
2088      if (option_core==1) then
2089        jm_re= abs(jm)
2090        jm_im=-abs(jm)
2091        jlm_re=jl*(jl+1)+jm_re+1
2092        jlm_im=jl*(jl+1)+jm_im+1
2093 !      Calculate spinor dependent coefficients
2094        sgnkappa=indlmn_j(3,jlmn)   !sign of kappa
2095        jmj=half*indlmn_j(8,jlmn)   !2mj is stored in indlmn_cor
2096        js=indlmn_cor(6,jlmn)       !1 is up, 2 is down
2097        if (sgnkappa==1) then
2098          if(js==1) then
2099            cgc= sqrt((dble(jl)-jmj+half)/dble(2*jl+1))
2100          else
2101            cgc=-sqrt((dble(jl)+jmj+half)/dble(2*jl+1))
2102          endif
2103        else
2104          if(js==1) then
2105            cgc= sqrt((dble(jl)+jmj+half)/dble(2*jl+1))
2106          else
2107            cgc= sqrt((dble(jl)-jmj+half)/dble(2*jl+1))
2108          endif
2109        endif
2110 
2111 !      Calculate factors to convert from complex to real sph. harm.
2112        if (jm<0) then
2113          fact_re=sqr_fourpi_over_3*half_sqrt2*cgc
2114          fact_im=-fact_re
2115        else if (jm>0) then
2116          fact_re=sqr_fourpi_over_3*half_sqrt2*cgc*(-1)**jm
2117          fact_im=fact_re
2118        else
2119          fact_re=sqr_fourpi_over_3
2120          fact_im=0
2121        end if
2122      else ! valence-valence case (real)
2123        js=1
2124        jlm_re=jlm ; jlm_im=jlm
2125        fact_re=sqr_fourpi_over_3
2126        fact_im=0
2127      end if
2128 
2129 !    Loop over final states
2130      do ilmn=1,lmn_size
2131        ilm=indlmn(4,ilmn)
2132        iln=indlmn(5,ilmn)
2133 
2134 !      >>>> Calculate g_ij=(g_x,g_y,g_z) = sqrt(4pi/3) int dOmega Ylm Ylm' S1-1,0,1
2135 !              using real Gaunt coefficients
2136        gx_re=zero;gy_re=zero;gz_re=zero         
2137        gx_im=zero;gy_im=zero;gz_im=zero
2138        if3=zero
2139 
2140 !      jl was set as a flag for invalid combinations
2141 !        i.e. m=-(l+1) or m=(l+1)
2142 !      In these cases, cgc=0 ; so gx=gy=gz=0 
2143        if (jl/=-1) then
2144          if3=intf3(iln,jln)
2145          klm_re=merge((jlm_re*(jlm_re-1))/2+ilm,(ilm*(ilm-1))/2+jlm_re,ilm<=jlm_re)
2146 
2147 !        Real parts
2148 !        M=-1
2149          ignt=pawang%gntselect(2,klm_re) !get index for L=1 M =-1 ilm jlm_re
2150          if (ignt/=0) gy_re=fact_re*pawang%realgnt(ignt)
2151 !        M=0
2152          ignt=pawang%gntselect(3,klm_re) !get index for L=1 M = 0 ilm jlm_re
2153          if (ignt/=0) gz_re=fact_re*pawang%realgnt(ignt)
2154 !        M=1
2155          ignt=pawang%gntselect(4,klm_re) !get index for L=1 M = 1 ilm jlm_re
2156          if (ignt/=0) gx_re=fact_re*pawang%realgnt(ignt)
2157 
2158 !        Imaginary parts
2159          if (option_core==1) then
2160            klm_im=merge((jlm_im*(jlm_im-1))/2+ilm,(ilm*(ilm-1))/2+jlm_im,ilm<=jlm_im)
2161 !          M=-1
2162            ignt=pawang%gntselect(2,klm_im) !get index for L=1 M =-1 ilm jlm_im
2163            if (ignt/=0) gy_im=fact_im*pawang%realgnt(ignt)
2164 !          M=0
2165            ignt=pawang%gntselect(3,klm_im) !get index for L=1 M = 0 ilm jlm_im
2166            if (ignt/=0) gz_im=fact_im*pawang%realgnt(ignt)
2167 !          M=1
2168            ignt=pawang%gntselect(4,klm_im) !get index for L=1 M = 1 ilm jlm_im
2169            if (ignt/=0) gx_im=fact_im*pawang%realgnt(ignt)
2170          end if
2171        end if
2172 
2173 !      >>>> Calculate Sigma X g_ij
2174 
2175        if (option_core==0.or.js==1) then
2176          !(Sigma^up-up X gij)_x = -gy*f_3
2177          soc_ij(1,1,1,ilmn,jlmn)=-if3*gy_re           ! real part
2178          soc_ij(2,1,1,ilmn,jlmn)=-if3*gy_im           ! imag part
2179          !(Sigma^up-up X gij)_y = gx*f_3
2180          soc_ij(1,1,2,ilmn,jlmn)= if3*gx_re           ! real part
2181          soc_ij(2,1,2,ilmn,jlmn)= if3*gx_im           ! imag part
2182          !(Sigma^up-up X gij)_z = 0
2183          soc_ij(1,1,3,ilmn,jlmn)= zero                ! real part
2184          soc_ij(2,1,3,ilmn,jlmn)= zero                ! imag part
2185 
2186          !(Sigma^dn-up X gij)_x = i.gz*f_3
2187          soc_ij(1,2,1,ilmn,jlmn)=-if3*gz_im           ! real part
2188          soc_ij(2,2,1,ilmn,jlmn)= if3*gz_re           ! imag part
2189          !(Sigma^dn-up X gij)_y = -gz*f_3
2190          soc_ij(1,2,2,ilmn,jlmn)=-if3*gz_re           ! real part
2191          soc_ij(2,2,2,ilmn,jlmn)=-if3*gz_im           ! imag part
2192          !(Sigma^dn-up X gij)_z = (gy-i.gx)*f_3
2193          soc_ij(1,2,3,ilmn,jlmn)= if3*(gy_re+gx_im)   ! real part
2194          soc_ij(2,2,3,ilmn,jlmn)= if3*(gy_im-gx_re)   ! imag part
2195 
2196        else if (option_core==1.and.js==2) then
2197          !(Sigma^up-dn X gij^dn)_x = -i.gz^dn*f_3
2198          soc_ij(1,1,1,ilmn,jlmn)= if3*gz_im           ! real part
2199          soc_ij(2,1,1,ilmn,jlmn)=-if3*gz_re           ! imag part
2200          !(Sigma^up-dn X gij^dn)_y = -gz^dn*f_3
2201          soc_ij(1,1,2,ilmn,jlmn)=-if3*gz_re           ! real part
2202          soc_ij(2,1,2,ilmn,jlmn)=-if3*gz_im           ! imag part
2203          !(Sigma^up-dn X gij^dn)_z = (gy^dn+i.gx^dn)*f_3
2204          soc_ij(1,1,3,ilmn,jlmn)= if3*(gy_re-gx_im)   ! real part
2205          soc_ij(2,1,3,ilmn,jlmn)= if3*(gy_im+gx_re)   ! imag part
2206 
2207          !(Sigma^dn-dn X gij^dn)_x =  gy^dn*f_3
2208          soc_ij(1,2,1,ilmn,jlmn)= if3*gy_re           ! real part
2209          soc_ij(2,2,1,ilmn,jlmn)= if3*gy_im           ! imag part
2210          !(Sigma^dn-dn X gij^dn)_y = -gx^dn*f_3
2211          soc_ij(1,2,2,ilmn,jlmn)=-if3*gx_re           ! real part
2212          soc_ij(2,2,2,ilmn,jlmn)=-if3*gx_im           ! imag part
2213          !(Sigma^dn-dn X gij^dn)_z = 0
2214          soc_ij(1,2,3,ilmn,jlmn)= zero                ! real part
2215          soc_ij(2,2,3,ilmn,jlmn)= zero                ! imag part
2216        end if
2217 
2218      end do ! ilmn
2219    end do ! jlmn
2220      
2221 !  Symetrization
2222    if (option_core==0.and.lmn_size>1) then
2223      do jlmn=2,lmn_size
2224        do ilmn=1,jlmn-1
2225          do ii=1,3
2226            do jj=1,2
2227              avg=half*(soc_ij(1,jj,ii,ilmn,jlmn)+soc_ij(1,jj,ii,jlmn,ilmn))
2228              soc_ij(1,jj,ii,ilmn,jlmn)=avg ; soc_ij(1,jj,ii,jlmn,ilmn)=avg
2229              avg=half*(soc_ij(2,jj,ii,ilmn,jlmn)+soc_ij(2,jj,ii,ilmn,jlmn))
2230              soc_ij(2,jj,ii,ilmn,jlmn)=avg ; soc_ij(2,jj,ii,jlmn,ilmn)=avg
2231            end do
2232          end do           
2233        end do
2234      end do
2235    end if
2236 
2237    ABI_FREE(dVdr)
2238    ABI_FREE(intf3)
2239 
2240  end do  ! iatom
2241  
2242 !Reduction in case of parallelism
2243  if (paral_atom) then
2244    call xmpi_sum(phisocphj,my_comm_atom,ierr)
2245  end if
2246  
2247 !Destroy atom table(s) used for parallelism
2248  call free_my_atmtab(my_atmtab,my_atmtab_allocated)
2249 
2250  end subroutine pawnabla_soc_init