LCOV - code coverage report
Current view: top level - src/95_drive - m_longwave.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 93.2 % 555 517
Test Date: 2026-09-19 15:24:51 Functions: 100.0 % 2 2

            Line data    Source code
       1              : !!****m* ABINIT/m_longwave
       2              : !! NAME
       3              : !!  m_longwave
       4              : !!
       5              : !! FUNCTION
       6              : !!  DFPT calculation of spatial and time dispersion properties
       7              : !!
       8              : !! COPYRIGHT
       9              : !!  Copyright (C) 2019-2026 ABINIT group (MR, MS)
      10              : !!  This file is distributed under the terms of the
      11              : !!  GNU General Public License, see ~abinit/COPYING
      12              : !!  or http://www.gnu.org/copyleft/gpl.txt .
      13              : !!
      14              : !! NOTES
      15              : !!
      16              : !! SOURCE
      17              : 
      18              : #if defined HAVE_CONFIG_H
      19              : #include "config.h"
      20              : #endif
      21              : 
      22              : #include "abi_common.h"
      23              : 
      24              : module m_longwave
      25              : 
      26              :  use defs_basis
      27              :  use m_errors
      28              :  use m_xmpi
      29              :  use defs_datatypes
      30              :  use defs_abitypes, only : MPI_type
      31              :  use defs_wvltypes
      32              :  use m_dtset
      33              :  use m_dtfil
      34              :  use m_xcdata
      35              :  use m_hdr
      36              :  use m_ebands
      37              :  use m_wffile
      38              : 
      39              :  use m_pspini,      only : pspini
      40              :  use m_common,      only : setup1
      41              :  use m_pawfgr,      only : pawfgr_type, pawfgr_init, pawfgr_destroy
      42              :  use m_pawrhoij,    only : pawrhoij_type
      43              :  use m_paw_dmft,    only : paw_dmft_type
      44              :  use m_pawrad,      only : pawrad_type
      45              :  use m_pawtab,      only : pawtab_type
      46              :  use m_drivexc,     only : check_kxc
      47              :  use m_rhotoxc,     only : rhotoxc
      48              :  use m_ioarr,       only : read_rhor
      49              :  use m_matrix,      only : matr3inv
      50              :  use m_symtk,       only : symmetrize_xred
      51              :  use m_kg,          only : kpgio,getcut,getph
      52              :  use m_inwffil,     only : inwffil
      53              :  use m_spacepar,    only : setsym
      54              :  use m_mkrho,       only : mkrho
      55              :  use m_fft,         only : fourdp
      56              :  use m_ddb,         only : ddb_type,lwcart
      57              :  use m_ddb_hdr,     only : ddb_hdr_type
      58              :  use m_mkcore,      only : mkcore
      59              :  use m_dfptlw_loop, only : dfptlw_loop
      60              :  use m_dfptlw_nv,   only : dfptlw_nv
      61              :  use m_dfptlw_pert, only : preca_ffnl
      62              :  use m_initylmg,    only : initylmg
      63              :  use m_geometry,    only : symredcart, d3lwsym, sylwtens
      64              :  use m_atm2fft,     only : atm2fft
      65              : 
      66              :  implicit none
      67              : 
      68              :  private
      69              : !!***
      70              : 
      71              :  public :: longwave
      72              : !!***
      73              : 
      74              : ! *************************************************************************
      75              : 
      76              : contains
      77              : !!***
      78              : 
      79              : !!****f* ABINIT/longwave
      80              : !! NAME
      81              : !!  longwave
      82              : !!
      83              : !! FUNCTION
      84              : !! Primary routine for conducting DFPT calculations of dispersion properties
      85              : !!
      86              : !! INPUTS
      87              : !!  codvsn = code version
      88              : !!  dtfil <type(datafiles_type)> = variables related to files
      89              : !!  dtset <type(dataset_type)> = all input variables for this dataset
      90              : !!  etotal = new total energy (no meaning at output)
      91              : !!  mpi_enreg=information about MPI pnarallelization
      92              : !!  occ(mband*nkpt*nsppol) = occupation number for each band and k
      93              : !!  xred(3,natom) = reduced atomic coordinates
      94              : !!
      95              : !! OUTPUT
      96              : !!  npwtot(nkpt) = total number of plane waves at each k point
      97              : !!
      98              : !! SIDE EFFECTS
      99              : !!  pawrad(ntypat*usepaw) <type(pawrad_type)>=paw radial mesh and related data
     100              : !!  pawtab(ntypat*usepaw) <type(pawtab_type)>=paw tabulated starting data
     101              : !!  psps <type(pseudopotential_type)> = variables related to pseudopotentials
     102              : !!
     103              : !! SOURCE
     104              : 
     105           17 : subroutine longwave(codvsn,dtfil,dtset,etotal,mpi_enreg,npwtot,occ,&
     106           17 :                    pawrad,pawtab,psps,xred)
     107              : 
     108              : #ifdef FC_INTEL
     109              : !DEC$ NOOPTIMIZE
     110              : #endif
     111              : 
     112              : !Arguments ------------------------------------
     113              :  !scalars
     114              :  real(dp),intent(inout) :: etotal
     115              :  character(len=8),intent(in) :: codvsn
     116              :  type(MPI_type),intent(inout) :: mpi_enreg
     117              :  type(datafiles_type),intent(in) :: dtfil
     118              :  type(dataset_type),intent(inout) :: dtset
     119              :  type(pseudopotential_type),intent(inout) :: psps
     120              :  !arrays
     121              :  integer,intent(out) :: npwtot(dtset%nkpt)
     122              :  real(dp),intent(inout) :: occ(dtset%mband*dtset%nkpt*dtset%nsppol),xred(3,dtset%natom)
     123              :  type(pawrad_type),intent(inout) :: pawrad(psps%ntypat*psps%usepaw)
     124              :  type(pawtab_type),intent(inout) :: pawtab(psps%ntypat*psps%usepaw)
     125              : 
     126              : !Local variables-------------------------------
     127              :  !scalars
     128              :  integer,parameter :: cplex1=1,formeig=0,response=1
     129              :  integer :: ask_accurate,bantot,dimffnl,dimffnl_i
     130              :  integer :: gscase,iatom,ierr,indx,ireadwf0,iscf_eff,itypat
     131              :  integer :: ider,idir0,idir
     132              :  integer :: i1dir,i1pert,i2dir,ii,i2pert,i3dir,i3pert
     133              :  integer :: me,mcg,mgfftf,natom,nfftf,nfftot,nfftotf,nhatdim,nhatgrdim
     134              : ! integer :: isym
     135              :  integer :: mpert,my_natom,n1,nkxc,nk3xc,ntypat,n3xccc,nylmgr
     136              :  integer :: optatm,optdyfr,opteltfr,optgr,optstr,optv,optn,optn2
     137              :  integer :: option,optorth,psp_gencond,rdwrpaw,spaceworld,timrev,tim_mkrho
     138              :  integer :: usexcnhat,useylmgr
     139              :  real(dp) :: bigexc,bigsxc,boxcut,ecore,ecutdg_eff,ecut_eff,etot
     140              :  real(dp) :: fermie,fermih,gsqcut,gsqcut_eff,gsqcutc_eff,residm
     141              :  real(dp) :: ucvol,vxcavg
     142              :  logical :: non_magnetic_xc,just_timdisp
     143              : ! logical :: has_strain
     144              :  character(len=500) :: msg
     145           17 :  type(ebands_t) :: bstruct
     146          884 :  type(ddb_hdr_type) :: ddb_hdr
     147           17 :  type(ddb_type) :: ddb
     148           17 :  type(paw_dmft_type) :: paw_dmft
     149              :  type(pawfgr_type) :: pawfgr
     150           17 :  type(hdr_type) :: hdr,hdr_den
     151              :  type(xcdata_type) :: xcdata
     152           17 :  type(wvl_data) :: wvl
     153              :  type(wffile_type) :: wffgs,wfftgs
     154              :  !arrays
     155              :  integer :: d3e_dir1(3),d3e_dir2(3),d3e_dir3(3)
     156              :  integer :: ngfft(18),ngfftf(18),perm(6)
     157              :  real(dp) :: dummy6(6),other_dummy6(6),gmet(3,3),gmet_for_kg(3,3),gprimd(3,3),gprimd_for_kg(3,3)
     158              :  real(dp) :: rmet(3,3),rprimd(3,3),rprimd_for_kg(3,3)
     159              :  real(dp) :: dum_gauss(0),dum_dyfrv(0),dum_eltfrxc(0)
     160              :  real(dp) :: dum_grn(0),dum_grv(0),dum_rhog(0),dum_vg(0)
     161           17 :  integer,allocatable :: atindx(:),atindx1(:)
     162           17 :  integer,allocatable :: blkflg(:,:,:,:,:,:),blkflg_car(:,:,:,:,:,:)
     163           17 :  integer,allocatable :: d3e_pert1(:),d3e_pert2(:),d3e_pert3(:)
     164           17 :  integer,allocatable :: indsym(:,:,:),irrzon(:,:,:),kg(:,:)
     165           17 :  integer,allocatable :: nattyp(:),npwarr(:),symrec(:,:,:)
     166           17 :  integer,allocatable :: rfpert(:,:,:,:,:,:)
     167           17 :  real(dp),allocatable :: cg(:,:)
     168           17 :  real(dp),allocatable :: d3etot(:,:,:,:,:,:,:),d3etot_car(:,:,:,:,:,:,:)
     169           17 :  real(dp),allocatable :: d3etot_nv(:,:,:,:,:,:,:),doccde(:)
     170           17 :  real(dp),allocatable :: eigen0(:),ffnl(:,:,:,:,:),ffnl_i(:,:,:,:,:)
     171           17 :  real(dp),allocatable :: grxc(:,:),kxc(:,:),vxc(:,:)
     172           17 :  real(dp),allocatable :: ncorespl(:,:,:),nhat(:,:),nhatgr(:,:,:)
     173           17 :  real(dp),allocatable :: phnons(:,:,:),ph1d(:,:),rhog(:,:),rhor(:,:),dummy_dyfrx2(:,:,:)
     174              : ! real(dp),allocatable :: symrel_cart(:,:,:)
     175           17 :  real(dp),allocatable :: dummy_vpsp(:),work(:),xccc3d(:)
     176           17 :  real(dp),allocatable :: ylm(:,:),ylmgr(:,:,:)
     177           17 :  type(pawrhoij_type),allocatable :: pawrhoij(:),pawrhoij_read(:)
     178              : ! *************************************************************************
     179              : 
     180              :  DBG_ENTER("COLL")
     181              : 
     182              : !Just time dispersion calculation
     183           17 :  just_timdisp=.false.
     184              :  if (dtset%lw_flexo==0.and.dtset%lw_qdrpl==0.and.&
     185           17 : &  dtset%lw_natopt==0.and.dtset%timdisp==1) just_timdisp=.true.
     186              : 
     187              : !Not valid for PAW
     188           17 :  if (psps%usepaw==1) then
     189            0 :    msg='This routine cannot be used for PAW!'
     190            0 :    ABI_BUG(msg)
     191              :  end if
     192              : 
     193              : !Not valid for finite wave-vector perturbations
     194           68 :  if (.not.just_timdisp.and.sqrt(sum(dtset%qptn**2))>tol8) then
     195            0 :    msg='This routine can only be used at q /= 0 for time dispersion calculation '
     196            0 :    ABI_BUG(msg)
     197              :  end if
     198              : 
     199              : !Only usable with spherical harmonics
     200           17 :  if (dtset%useylm/=1.and.(.not.just_timdisp.and.dtset%lw_qdrpl/=0.or.dtset%lw_flexo/=0)) then
     201            0 :    msg='This routine can only be used with useylm/=1 for the spatial dispersion given by lw_natopt=1'
     202            0 :    ABI_BUG(msg)
     203              :  end if
     204              : 
     205              : !Not valid for spin-dependent calculations
     206           17 :  if (.not.just_timdisp.and.(dtset%nspinor/=1.or.dtset%nsppol/=1.or.dtset%nspden/=1)) then
     207            0 :    msg='This routine cannot be used for spin-dependent calculations of spatial dispersion'
     208            0 :    ABI_BUG(msg)
     209              :  end if
     210              : 
     211              : !Not usable with core electron density corrections and flexo
     212           17 :  if (.not.just_timdisp.and.psps%n1xccc/=0.and.dtset%lw_flexo/=0) then
     213            0 :    msg='This routine cannot be used to calculate flexoelectric properties with n1xccc/=0'
     214            0 :    ABI_BUG(msg)
     215              :  end if
     216              : 
     217              : !Only usable for insulators
     218              :  if(0>dtset%occopt .and. dtset%occopt>2)then
     219              :    msg='This routine cannot be used with metallic occupations'
     220              :  end if
     221              : 
     222              : !Define some data
     223           17 :  ntypat=psps%ntypat
     224           17 :  natom=dtset%natom
     225           17 :  timrev=1
     226              : 
     227              : !Init spaceworld
     228           17 :  spaceworld=mpi_enreg%comm_cell
     229           17 :  my_natom=mpi_enreg%my_natom
     230           17 :  me = xmpi_comm_rank(spaceworld)
     231              : 
     232              : !Define FFT grid(s) sizes (be careful !)
     233              : !See NOTES in the comments at the beginning of this file.
     234           17 :  call pawfgr_init(pawfgr,dtset,mgfftf,nfftf,ecut_eff,ecutdg_eff,ngfft,ngfftf)
     235           68 :  nfftot=product(ngfft(1:3))
     236              :  nfftotf=product(ngfftf(1:3))
     237              : 
     238              : !Set up for iterations
     239              :  call setup1(dtset%acell_orig(1:3,1),bantot,dtset,&
     240              : & ecutdg_eff,ecut_eff,gmet,gprimd,gsqcut_eff,gsqcutc_eff,&
     241              : & ngfftf,ngfft,dtset%nkpt,dtset%nsppol,&
     242           17 : & response,rmet,dtset%rprim_orig(1:3,1:3,1),rprimd,ucvol,psps%usepaw)
     243              : 
     244              : !Define the set of admitted perturbations taking into account
     245              : !the possible permutations
     246              : !  -> natom+8 refers to ddq perturbation (spatial dispersion)
     247              : !  -> natom+9 refers to ddw perturbation (time dispersion)
     248           17 :  if (dtset%timdisp==0) then
     249           11 :    mpert=natom+8
     250              :  else
     251            6 :    mpert=natom+9
     252            6 :    if (dtset%d3e_pert1_magn==2.or.dtset%d3e_pert2_magn==2) mpert=2*dtset%natom+11
     253              :  end if
     254          119 :  ABI_MALLOC(blkflg,(3,mpert,3,mpert,3,mpert))
     255          119 :  ABI_MALLOC(d3etot,(2,3,mpert,3,mpert,3,mpert))
     256           68 :  ABI_MALLOC(d3etot_nv,(2,3,mpert,3,mpert,3,mpert))
     257           68 :  ABI_MALLOC(rfpert,(3,mpert,3,mpert,3,mpert))
     258           51 :  ABI_MALLOC(d3e_pert1,(mpert))
     259           34 :  ABI_MALLOC(d3e_pert2,(mpert))
     260           34 :  ABI_MALLOC(d3e_pert3,(mpert))
     261      2623081 :  blkflg(:,:,:,:,:,:) = 0
     262      6485593 :  d3etot(:,:,:,:,:,:,:) = zero
     263      6485593 :  d3etot_nv(:,:,:,:,:,:,:) = zero
     264      2623081 :  rfpert(:,:,:,:,:,:) = 0
     265          743 :  d3e_pert1(:) = 0 ; d3e_pert2(:) = 0 ; d3e_pert3(:) = 0
     266              : 
     267              : !Spatial-dispersion perturbations
     268           17 :  if (.not.just_timdisp) d3e_pert3(natom+8)=1
     269              : 
     270           17 :  if (dtset%lw_qdrpl==1) then
     271            7 :    d3e_pert1(natom+2)=1
     272           24 :    d3e_pert2(1:natom)=1
     273              :  end if
     274              : 
     275           17 :  if (dtset%lw_flexo==2.or.dtset%lw_flexo==1) then
     276            3 :    d3e_pert1(natom+2)=1
     277            9 :    d3e_pert2(natom+3:natom+4)=1
     278              :  end if
     279              : 
     280           17 :  if (dtset%lw_flexo==3.or.dtset%lw_flexo==1) then
     281            9 :    d3e_pert1(natom+2)=1 ; d3e_pert1(1:natom)=1
     282            9 :    d3e_pert2(1:natom)=1
     283              :  end if
     284              : 
     285           17 :  if (dtset%lw_flexo==4.or.dtset%lw_flexo==1) then
     286            9 :    d3e_pert1(1:natom)=1
     287            9 :    d3e_pert2(natom+3:natom+4)=1
     288              :  end if
     289              : 
     290           17 :  if (dtset%lw_natopt==1) then
     291            1 :    d3e_pert1(natom+2)=1
     292            1 :    d3e_pert2(natom+2)=1
     293              :  end if
     294              : 
     295           17 :  perm(:)=0
     296          259 :  do i1pert = 1, mpert
     297         4183 :    do i2pert = 1, mpert
     298        75694 :      do i3pert = 1, mpert
     299        71528 :        perm(1)=d3e_pert1(i1pert)*d3e_pert2(i2pert)*d3e_pert3(i3pert)
     300              : !       perm(2)=d3e_pert1(i1pert)*d3e_pert2(i3pert)*d3e_pert3(i2pert)
     301              : !       perm(3)=d3e_pert1(i2pert)*d3e_pert2(i1pert)*d3e_pert3(i3pert)
     302              : !       perm(4)=d3e_pert1(i2pert)*d3e_pert2(i3pert)*d3e_pert3(i1pert)
     303              : !       perm(5)=d3e_pert1(i3pert)*d3e_pert2(i2pert)*d3e_pert3(i1pert)
     304              : !       perm(6)=d3e_pert1(i3pert)*d3e_pert2(i1pert)*d3e_pert3(i2pert)
     305       506726 :        if ( sum(perm(:)) > 0 ) rfpert(:,i1pert,:,i2pert,:,i3pert)=1
     306              :      end do
     307              :    end do
     308              :  end do
     309              : 
     310              : !Time-dispersion perturbations
     311              : ! d3e_pert1(:) = 0 ; d3e_pert2(:) = 0 ; d3e_pert3(:) = 0
     312              : ! d3e_dir1(:) = 0 ; d3e_dir2(:) = 0 ; d3e_dir3(:) = 0
     313           17 :  if (dtset%timdisp==1) then
     314            6 :    d3e_pert3(natom+9)=1
     315            6 :    d3e_dir3(1)=1
     316            6 :    d3e_dir3(2)=0
     317            6 :    d3e_dir3(3)=0
     318              : 
     319              :    !Atomic displacements
     320           10 :    if (dtset%d3e_pert1_phon==1) d3e_pert1(dtset%d3e_pert1_atpol(1):dtset%d3e_pert1_atpol(2))=1
     321           10 :    if (dtset%d3e_pert2_phon==1) d3e_pert2(dtset%d3e_pert2_atpol(1):dtset%d3e_pert2_atpol(2))=1
     322              : 
     323              :    !Electric fields
     324            6 :    if (dtset%d3e_pert1_elfd/=0) d3e_pert1(natom+2)=1
     325            6 :    if (dtset%d3e_pert2_elfd/=0) d3e_pert2(natom+2)=1
     326              : 
     327              :    !Macroscopic hspinfields
     328            6 :    if (dtset%d3e_pert1_magn==1) d3e_pert1(natom+5)=1
     329            6 :    if (dtset%d3e_pert2_magn==1) d3e_pert2(natom+5)=1
     330              : 
     331              :    !Local hspinfields
     332            9 :    if (dtset%d3e_pert1_magn==2) d3e_pert1(natom+11+dtset%d3e_pert1_magat(1):natom+11+dtset%d3e_pert1_magat(2))=1
     333            9 :    if (dtset%d3e_pert2_magn==2) d3e_pert2(natom+11+dtset%d3e_pert2_magat(1):natom+11+dtset%d3e_pert2_magat(2))=1
     334              : 
     335            6 :    perm(:)=0
     336          128 :    do i1pert = 1, mpert
     337          488 :      d3e_dir1(:)=dtset%d3e_pert1_dir(:)
     338          122 :      if (i1pert>natom+11.and.i1pert<=2*natom+11) &
     339           96 :    & d3e_dir1(:)=dtset%d3e_pert1_magdir(:)
     340          494 :      do i1dir = 1, 3
     341         8186 :        do i2pert = 1, mpert
     342        30792 :          d3e_dir2(:)=dtset%d3e_pert2_dir(:)
     343         7698 :          if (i2pert>natom+11.and.i2pert<=2*natom+11) &
     344         6624 :        & d3e_dir2(:)=dtset%d3e_pert2_magdir(:)
     345        31158 :          do i2dir = 1, 3
     346        53886 :            do i3pert = natom+9, natom+9
     347       115470 :              do i3dir = 1, 3
     348              :                perm(1)=d3e_pert1(i1pert)*d3e_dir1(i1dir)* &
     349              :              &         d3e_pert2(i2pert)*d3e_dir2(i2dir)* &
     350        69282 :              &         d3e_pert3(i3pert)*d3e_dir3(i3dir)
     351       508068 :                if ( sum(perm(:)) > 0 ) rfpert(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)=1
     352              :              end do
     353              :            end do
     354              :          end do
     355              :        end do
     356              :      end do
     357              :    end do
     358              :  end if
     359              : 
     360              : !Do symmetry stuff
     361           68 :  ABI_MALLOC(irrzon,(nfftot**(1-1/dtset%nsym),2,(dtset%nspden/dtset%nsppol)-3*(dtset%nspden/4)))
     362           68 :  ABI_MALLOC(phnons,(2,nfftot**(1-1/dtset%nsym),(dtset%nspden/dtset%nsppol)-3*(dtset%nspden/4)))
     363           68 :  ABI_MALLOC(indsym,(4,dtset%nsym,natom))
     364           51 :  ABI_MALLOC(symrec,(3,3,dtset%nsym))
     365       715682 :  irrzon=0;indsym=0;symrec=0;phnons=zero
     366              : !If the density is to be computed by mkrho, need irrzon and phnons
     367           17 :  iscf_eff=0;if(dtset%getden==0)iscf_eff=1
     368              :  call setsym(indsym,irrzon,iscf_eff,natom,&
     369              : & nfftot,ngfft,dtset%nspden,dtset%nsppol,dtset%nsym,&
     370           17 : & phnons,dtset%symafm,symrec,dtset%symrel,dtset%tnons,dtset%typat,xred)
     371              : 
     372              : !Symmetrize atomic coordinates over space group elements:
     373           17 :  call symmetrize_xred(natom,dtset%nsym,dtset%symrel,dtset%tnons,xred,indsym=indsym)
     374              : 
     375              : ! Get symmetries in cartesian coordinates
     376              : ! ABI_MALLOC(symrel_cart, (3, 3, dtset%nsym))
     377              : ! do isym =1,dtset%nsym
     378              : !   call symredcart(rprimd, gprimd, symrel_cart(:,:,isym), dtset%symrel(:,:,isym))
     379              : !   ! purify operations in cartesian coordinates.
     380              : !   where (abs(symrel_cart(:,:,isym)) < tol14)
     381              : !     symrel_cart(:,:,isym) = zero
     382              : !   end where
     383              : ! end do
     384              : 
     385              : ! call sylwtens(indsym,mpert,natom,dtset%nsym,rfpert,symrec,dtset%symrel,symrel_cart)
     386           17 :  call sylwtens(indsym,mpert,natom,dtset%nsym,rfpert,symrec,dtset%symrel)
     387              : 
     388           17 :  write(msg,'(a,a,a,a,a)') ch10, &
     389           17 : & ' The list of irreducible elements of the spatial-dispersion third-order energy derivatives is: ', ch10,&
     390           34 : & ' (in reduced coordinates except for strain and hspinfield perturbations) ', ch10
     391           17 :  call wrtout(ab_out,msg,'COLL')
     392           17 :  call wrtout(std_out,msg,'COLL')
     393              : 
     394           17 :  write(msg,'(12x,a)') 'i1dir   i1pert  i2dir   i2pert  i3dir  i3pert'
     395           17 :  call wrtout(ab_out,msg,'COLL')
     396           17 :  call wrtout(std_out,msg,'COLL')
     397           17 :  n1 = 0
     398          259 :  do i3pert = 1, mpert
     399          985 :    do i3dir = 1, 3
     400        12740 :      do i2pert = 1, mpert
     401        47814 :        do i2dir = 1,3
     402       690840 :          do i1pert = 1, mpert
     403      2610324 :            do i1dir = 1, 3
     404      2575008 :              if (rfpert(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)==1) then
     405          611 :                n1 = n1 + 1
     406          611 :                write(msg,'(2x,i4,a,6(5x,i3))') n1,')', &
     407         1222 :              & i1dir,i1pert,i2dir,i2pert,i3dir,i3pert
     408          611 :                call wrtout(ab_out,msg,'COLL')
     409          611 :                call wrtout(std_out,msg,'COLL')
     410      1930645 :              else if (rfpert(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)==-2) then
     411          263 :                blkflg(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert) = 1
     412          263 :                if (dtset%prtvol>=10) then
     413            0 :                  n1 = n1 + 1
     414            0 :                  write(msg,'(2x,i4,a,6(5x,i3),a)') n1,')', &
     415            0 :   &               i1dir,i1pert,i2dir,i2pert,i3dir,i3pert,' => must be zero, not computed'
     416            0 :                  call wrtout(ab_out,msg,'COLL')
     417            0 :                  call wrtout(std_out,msg,'COLL')
     418              :                end if
     419      1930382 :              else if (rfpert(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)==-1) then
     420          612 :                if (dtset%prtvol>=10) then
     421            0 :                  n1 = n1 + 1
     422            0 :                  write(msg,'(2x,i4,a,6(5x,i3),a)') n1,')', &
     423            0 :   &               i1dir,i1pert,i2dir,i2pert,i3dir,i3pert,' => symmetric of another element, not computed'
     424            0 :                  call wrtout(ab_out,msg,'COLL')
     425            0 :                  call wrtout(std_out,msg,'COLL')
     426              :                end if
     427              :              end if
     428              :            end do
     429              :          end do
     430              :        end do
     431              :      end do
     432              :    end do
     433              :  end do
     434           17 :  write(msg,'(a,a)') ch10,ch10
     435           17 :  call wrtout(ab_out,msg,'COLL')
     436           17 :  call wrtout(std_out,msg,'COLL')
     437              : 
     438              : !In some cases (e.g. getcell/=0), the plane wave vectors have
     439              : !to be generated from the original simulation cell
     440           17 :  rprimd_for_kg=rprimd
     441           17 :  if (dtset%getcell/=0.and.dtset%usewvl==0) rprimd_for_kg=dtset%rprimd_orig(:,:,1)
     442           17 :  call matr3inv(rprimd_for_kg,gprimd_for_kg)
     443          680 :  gmet_for_kg=matmul(transpose(gprimd_for_kg),gprimd_for_kg)
     444              : 
     445              : !Set up the basis sphere of planewaves
     446           51 :  ABI_MALLOC(kg,(3,dtset%mpw*dtset%mkmem))
     447           51 :  ABI_MALLOC(npwarr,(dtset%nkpt))
     448              :  call kpgio(ecut_eff,dtset%exchn2n3d,gmet_for_kg,dtset%istwfk,kg,&
     449              : & dtset%kptns,dtset%mkmem,dtset%nband,dtset%nkpt,'PERS',mpi_enreg,dtset%mpw,npwarr,npwtot,&
     450           17 : & dtset%nsppol)
     451              : 
     452              : !Open and read pseudopotential files
     453              :  ecore=zero
     454              :  call pspini(dtset,dtfil,ecore,psp_gencond,gsqcutc_eff,gsqcut_eff,pawrad,pawtab,&
     455           17 : & psps,rprimd,comm_mpi=mpi_enreg%comm_cell)
     456              : 
     457              : !Initialize band structure datatype
     458           17 :  call bstruct%from_dtset(dtset, npwarr)
     459              : 
     460              : !Initialize PAW atomic occupancies to zero
     461           17 :  ABI_MALLOC(pawrhoij,(0))
     462              : 
     463              : !Initialize header
     464           17 :  gscase=0
     465              :  call hdr%init(bstruct,codvsn,dtset,pawtab,gscase,psps,wvl%descr, &
     466           17 : & comm_atom=mpi_enreg%comm_atom, mpi_atmtab=mpi_enreg%my_atmtab)
     467              : 
     468              : !Update header, with evolving variables, when available
     469              : !Here, rprimd, xred and occ are available
     470           17 :  etot=hdr%etot ; fermie=hdr%fermie ; fermih=hdr%fermih ; residm=hdr%residm
     471              : 
     472              : !If parallelism over atom, hdr is distributed
     473              :  call hdr%update(bantot,etot,fermie,fermih,&
     474              : & residm,rprimd,occ,pawrhoij,xred,dtset%amu_orig(:,1), &
     475           17 : & comm_atom=mpi_enreg%comm_atom, mpi_atmtab=mpi_enreg%my_atmtab)
     476              : 
     477              : !Clean band structure datatype (should use it more in the future !)
     478           17 :  call bstruct%free()
     479              : 
     480              : !Initialize wavefunction files and wavefunctions.
     481           17 :  mcg=dtset%mpw*dtset%nspinor*dtset%mband*dtset%mkmem*dtset%nsppol
     482           51 :  ABI_STAT_MALLOC(cg,(2,mcg), ierr)
     483           17 :  ABI_CHECK(ierr==0, "out-of-memory in cg")
     484              : 
     485           51 :  ABI_MALLOC(eigen0,(dtset%mband*dtset%nkpt*dtset%nsppol))
     486         7121 :  eigen0(:)=zero ; ask_accurate=1
     487           17 :  optorth=0
     488              : 
     489           17 :  ireadwf0=1
     490          221 :  hdr%rprimd=rprimd_for_kg ! We need the rprimd that was used to generate de G vectors
     491           17 :  if (.not.just_timdisp) then
     492              :    call inwffil(ask_accurate,cg,dtset,dtset%ecut,ecut_eff,eigen0,dtset%exchn2n3d,&
     493              :   & formeig,hdr,ireadwf0,dtset%istwfk,kg,dtset%kptns,&
     494              :   & dtset%localrdwf,dtset%mband,mcg,dtset%mkmem,mpi_enreg,dtset%mpw,&
     495              :   & dtset%nband,ngfft,dtset%nkpt,npwarr,dtset%nsppol,dtset%nsym,&
     496              :   & occ,optorth,dtset%symafm,dtset%symrel,dtset%tnons,&
     497           11 :   & dtfil%unkg,wffgs,wfftgs,dtfil%unwffgs,dtfil%fnamewffk,wvl)
     498          143 :    hdr%rprimd=rprimd
     499              : 
     500              :   !Close wffgs, if it was ever opened (in inwffil)
     501           11 :    if (ireadwf0==1) then
     502           11 :      call WffClose(wffgs,ierr)
     503              :    end if
     504              :  end if
     505              : 
     506              : !Generate an index table of atoms, in order for them to be used
     507              : !type after type.
     508           51 :  ABI_MALLOC(atindx,(natom))
     509           34 :  ABI_MALLOC(atindx1,(natom))
     510           51 :  ABI_MALLOC(nattyp,(ntypat))
     511           48 :  indx=1
     512           48 :  do itypat=1,ntypat
     513           31 :    nattyp(itypat)=0
     514          181 :    do iatom=1,natom
     515          164 :      if(dtset%typat(iatom)==itypat)then
     516           68 :        atindx(iatom)=indx
     517           68 :        atindx1(indx)=iatom
     518           68 :        indx=indx+1
     519           68 :        nattyp(itypat)=nattyp(itypat)+1
     520              :      end if
     521              :    end do
     522              :  end do
     523              : 
     524              : !Derivative of occupations is always zero for non metallic systems
     525           51 :  ABI_MALLOC(doccde,(dtset%mband*dtset%nkpt*dtset%nsppol))
     526         7121 :  doccde(:)=zero
     527              : 
     528              : !Read ground-state charge density from diskfile in case getden /= 0
     529              : !or compute it from wfs that were read previously : rhor
     530              : 
     531           51 :  ABI_MALLOC(rhog,(2,nfftf))
     532           68 :  ABI_MALLOC(rhor,(nfftf,dtset%nspden))
     533              : 
     534           17 :  if (.not.just_timdisp) then
     535           11 :    if (dtset%getden /= 0 .or. dtset%irdden /= 0) then
     536              :      ! Read rho1(r) from a disk file and broadcast data.
     537              :      ! This part is not compatible with MPI-FFT (note single_proc=.True. below)
     538              : 
     539            0 :      rdwrpaw=psps%usepaw
     540            0 :      ABI_MALLOC(pawrhoij_read,(0))
     541              : 
     542              : !
     543              :   !  MT july 2013: Should we read rhoij from the density file ?
     544              :      call read_rhor(dtfil%fildensin, cplex1, dtset%nspden, nfftf, ngfftf, rdwrpaw, mpi_enreg, rhor, &
     545            0 :      hdr_den, pawrhoij_read, spaceworld, check_hdr=hdr)
     546            0 :      etotal = hdr_den%etot; call hdr_den%free()
     547              : 
     548            0 :      ABI_FREE(pawrhoij_read)
     549              : 
     550              :   !  Compute up+down rho(G) by fft
     551            0 :      ABI_MALLOC(work,(nfftf))
     552            0 :      work(:)=rhor(:,1)
     553            0 :      call fourdp(1,rhog,work,-1,mpi_enreg,nfftf,1,ngfftf,0)
     554            0 :      ABI_FREE(work)
     555              :    else
     556              :   !  Obtain the charge density from read wfs
     557              :   !  Be careful: in PAW, compensation density has to be added !
     558           11 :      tim_mkrho=4
     559           11 :      paw_dmft%use_sc_dmft=0 ! respfn with dmft not implemented
     560           11 :      paw_dmft%use_dmft=0 ! respfn with dmft not implemented
     561              : 
     562              :        call mkrho(cg,dtset,gprimd,irrzon,kg,mcg,&
     563           11 :   &     mpi_enreg,npwarr,occ,paw_dmft,phnons,rhog,rhor,rprimd,tim_mkrho,ucvol,wvl%den,wvl%wfs)
     564              :    end if ! getden
     565              :   ! ABI_FREE(cg)
     566              :  end if
     567              : 
     568              : !Compute large sphere cut-off gsqcut
     569           17 :  call getcut(boxcut,dtset%ecut,gmet,gsqcut,dtset%iboxcut,std_out,dtset%qptn,dtset%ngfft)
     570              : 
     571              : !Generate the 1-dimensional phases
     572           51 :  ABI_MALLOC(ph1d,(2,3*(2*mgfftf+1)*dtset%natom))
     573           17 :  call getph(atindx,dtset%natom,dtset%ngfft(1),dtset%ngfft(2),dtset%ngfft(3),ph1d,xred)
     574              : 
     575              : !Pseudo core electron density by method 2
     576              : !TODO: The tasks to adapt the code to consider n3xccc in the long-wave
     577              : !driver are under way.
     578           17 :  n3xccc=0;if (psps%n1xccc/=0) n3xccc=nfftf
     579           51 :  ABI_MALLOC(xccc3d,(n3xccc))
     580           17 :  if (.not.just_timdisp) then
     581           44 :    ABI_MALLOC(ncorespl,(psps%mqgrid_vl,2,ntypat))
     582           11 :    if (psps%n1xccc/=0) then
     583            6 :      ABI_MALLOC(dummy_dyfrx2,(3,3,natom)) ! dummy
     584            2 :      if (psps%nc_xccc_gspace==1) then
     585            0 :        ABI_MALLOC(dummy_vpsp,(nfftf))
     586            0 :        optatm=1;optdyfr=0;opteltfr=0;optgr=0;optstr=0;optv=0;optn=n3xccc/nfftf;optn2=1
     587              :        call atm2fft(atindx1,xccc3d,dummy_vpsp,dummy_dyfrx2,dum_dyfrv,dum_eltfrxc,dum_gauss,gmet,gprimd,&
     588              :     &   dum_grn,dum_grv,gsqcut,mgfftf,psps%mqgrid_vl,natom,nattyp,nfftf,ngfftf,&
     589              :     &   ntypat,optatm,optdyfr,opteltfr,optgr,optn,optn2,optstr,optv,psps,pawtab,ph1d,psps%qgrid_vl,&
     590            0 :     &   dtset%qprtrb,dtset%rcut,dum_rhog,rprimd,dummy6,other_dummy6,ucvol,psps%usepaw,dum_vg,dum_vg,dum_vg,dtset%vprtrb,psps%vlspl)
     591              : 
     592            0 :        ABI_FREE(dummy_vpsp)
     593              :      end if
     594            2 :      if (psps%nc_xccc_gspace==0) then
     595            2 :        option=1
     596            2 :        ABI_MALLOC(vxc,(0,0)) ! dummy
     597            6 :        ABI_MALLOC(grxc,(3,natom))
     598              :        call mkcore(dummy6,dummy_dyfrx2,grxc,mpi_enreg,natom,nfftf,dtset%nspden,ntypat,&
     599              :     &   ngfftf(1),psps%n1xccc,ngfftf(2),ngfftf(3),option,rprimd,dtset%typat,ucvol,vxc,&
     600            2 :     &   psps%xcccrc,psps%xccc1d,xccc3d,xred)
     601            2 :        ABI_FREE(vxc) ! dummy
     602            2 :        ABI_FREE(grxc) ! dummy
     603              :      end if
     604            2 :      ABI_FREE(dummy_dyfrx2) ! dummy
     605              : 
     606              :      !Write the spl interpolation of the pseudo core density for all atom types
     607            6 :      do itypat= 1, ntypat
     608        24022 :        ncorespl(:,:,itypat)= psps%nctab(itypat)%tcorespl(:,:)
     609              :      end do
     610              :    end if
     611              :  end if
     612              : 
     613              : !Set up xc potential. Compute kxc here.
     614              : !TODO: Iclude nonlinear core corrections (see m_respfn_driver.F90)
     615           17 :  option=2 ; nk3xc=1
     616           17 :  nkxc=2*min(dtset%nspden,2)-1;if(dtset%xclevel==2)nkxc=12*min(dtset%nspden,2)-5
     617           17 :  call check_kxc(dtset%ixc,dtset%optdriver)
     618           68 :  ABI_MALLOC(kxc,(nfftf,nkxc))
     619           68 :  ABI_MALLOC(vxc,(nfftf,dtset%nspden))
     620              : 
     621           17 :  nhatgrdim=0;nhatdim=0
     622           17 :  ABI_MALLOC(nhat,(0,0))
     623           17 :  ABI_MALLOC(nhatgr,(0,0,0))
     624           17 :  non_magnetic_xc=.false.
     625              : 
     626           17 :  usexcnhat=0
     627           17 :  bigexc=zero
     628           17 :  bigsxc=zero
     629              : 
     630           17 :  if (.not.just_timdisp) then
     631           11 :    call xcdata_init(xcdata,dtset=dtset)
     632              :    call rhotoxc(bigexc,bigsxc,kxc,mpi_enreg,nfftf,ngfftf,&
     633              :   & nhat,nhatdim,nhatgr,nhatgrdim,nkxc,nk3xc,non_magnetic_xc,n3xccc,option,rhor,&
     634           11 :   & rprimd,usexcnhat,vxc,vxcavg,xccc3d,xcdata)
     635              :  end if
     636              : 
     637           17 :  ABI_FREE(xccc3d)
     638              : 
     639              : !Set up the spherical harmonics (Ylm) and gradients at each k point
     640           17 :  if (psps%useylm==1) then
     641           11 :    useylmgr=1; option=2 ; nylmgr=9
     642           44 :    ABI_MALLOC(ylm,(dtset%mpw*dtset%mkmem,psps%mpsang*psps%mpsang*psps%useylm))
     643           55 :    ABI_MALLOC(ylmgr,(dtset%mpw*dtset%mkmem,nylmgr,psps%mpsang*psps%mpsang*psps%useylm*useylmgr))
     644           11 :    if (.not.just_timdisp) then
     645              :      call initylmg(gprimd,kg,dtset%kptns,dtset%mkmem,mpi_enreg,&
     646              :    & psps%mpsang,dtset%mpw,dtset%nband,dtset%nkpt,npwarr,dtset%nsppol,option,&
     647           11 :    & rprimd,ylm,ylmgr)
     648              :    end if
     649              :  end if
     650              : 
     651              : !Compute nonlocal form factors ffnl1, for all atoms and all k-points.
     652           17 :  if (dtset%ffnl_lw == 0) then
     653           16 :    if (dtset%lw_natopt==1) then
     654            1 :      ider=1;dimffnl=4;dimffnl_i=2
     655            7 :      ABI_MALLOC(ffnl,(dtset%mkmem,dtset%mpw,dimffnl,psps%lmnmax,psps%ntypat))
     656            7 :      ABI_MALLOC(ffnl_i,(dtset%mkmem,dtset%mpw,dimffnl_i,psps%lmnmax,psps%ntypat))
     657            4 :      do idir=1, 3
     658            3 :        idir0=idir
     659            3 :        if (.not.just_timdisp) then
     660              :          call preca_ffnl(dimffnl_i,ffnl_i,gmet,gprimd,ider,idir0,kg, &
     661              :        & dtset%kptns,dtset%mband,dtset%mkmem,mpi_enreg,dtset%mpw, &
     662            3 :        & dtset%nkpt,npwarr,nylmgr,psps,rmet,useylmgr,ylm,ylmgr)
     663              :        end if
     664       284157 :        ffnl(:,:,1,:,:)=ffnl_i(:,:,1,:,:)
     665       284158 :        ffnl(:,:,1+idir,:,:)=ffnl_i(:,:,2,:,:)
     666              :      end do
     667            1 :      ABI_FREE(ffnl_i)
     668            1 :      if (psps%useylm==1) then
     669            1 :        useylmgr=0
     670            1 :        ABI_FREE(ylmgr)
     671            3 :        ABI_MALLOC(ylmgr,(dtset%mpw*dtset%mkmem,nylmgr,psps%mpsang*psps%mpsang*psps%useylm*useylmgr))
     672              :      end if
     673              :    else
     674           15 :      if (dtset%lw_qdrpl==1.or.dtset%lw_flexo==3) ider=1; idir0=4; dimffnl=4
     675           15 :      if (dtset%lw_flexo==1.or.dtset%lw_flexo==2.or.dtset%lw_flexo==4) then
     676            2 :        ider=2; idir0=4; dimffnl=10
     677              :      end if
     678          105 :      ABI_MALLOC(ffnl,(dtset%mkmem,dtset%mpw,dimffnl,psps%lmnmax,psps%ntypat))
     679           15 :      if (.not.just_timdisp) then
     680              :        call preca_ffnl(dimffnl,ffnl,gmet,gprimd,ider,idir0,kg, &
     681              :      & dtset%kptns,dtset%mband,dtset%mkmem,mpi_enreg,dtset%mpw, &
     682            9 :      & dtset%nkpt,npwarr,nylmgr,psps,rmet,useylmgr,ylm,ylmgr)
     683              :      end if
     684           15 :      useylmgr=0
     685           15 :      ABI_SFREE(ylmgr)
     686           45 :      ABI_MALLOC(ylmgr,(dtset%mpw*dtset%mkmem,nylmgr,psps%mpsang*psps%mpsang*psps%useylm*useylmgr))
     687              :    end if
     688            1 :  else if (dtset%ffnl_lw == 1) then
     689            1 :    dimffnl=0
     690            5 :    ABI_MALLOC(ffnl,(dtset%mkmem,dtset%mpw,dimffnl,psps%lmnmax,psps%ntypat))
     691              :  end if
     692              : 
     693              : !#############  SPATIAL-DISPERSION PROPERTIES CALCULATION  ###########################
     694              : 
     695              : !Anounce start of spatial-dispersion calculation
     696         1394 :  write(msg, '(a,80a,a,a,a)' ) ch10,('=',ii=1,80),ch10,&
     697         1411 : &   ' ==> Compute spatial-dispersion 3rd-order energy derivatives <== ',ch10
     698           17 :  call wrtout(std_out,msg,'COLL')
     699           17 :  call wrtout(ab_out,msg,'COLL')
     700              : 
     701           17 :  if (dtset%prtvol>=10) then
     702            0 :    write(msg,'(5a)') ' CAUTION: Individual contributions to the 3rd-order energy derivatives ',ch10, &
     703            0 :                    & ' are not written in a unified form. Mixed cartesian/reduced coordinates ',ch10, &
     704            0 :                    & ' and/or type-I/type-II forms are used.'
     705            0 :    call wrtout(std_out,msg,'COLL')
     706            0 :    call wrtout(ab_out,msg,'COLL')
     707              :  end if
     708              : 
     709              : !Calculate the nonvariational Ewald terms
     710           17 :  if (dtset%lw_flexo==1.or.dtset%lw_flexo==3.or.dtset%lw_flexo==4) then
     711              :    call dfptlw_nv(d3etot_nv,dtset,gmet,gprimd,mpert,my_natom,rfpert,rmet,rprimd,ucvol,xred,psps%ziontypat, &
     712            3 :   & mpi_atmtab=mpi_enreg%my_atmtab,comm_atom=mpi_enreg%comm_atom)
     713              :  end if
     714              : 
     715              : !Main loop over the perturbations to calculate the stationary part
     716              :  call dfptlw_loop(atindx,blkflg,cg,codvsn,d3e_pert1,d3e_pert2,d3etot,dimffnl,dtfil,dtset,&
     717              : & ffnl,gmet,gprimd,gsqcut,&
     718              : & hdr,just_timdisp,kg,kxc,dtset%mband,dtset%mgfft,&
     719              : & dtset%mkmem,dtset%mk1mem,mpert,mpi_enreg,dtset%mpw,natom,nattyp,ncorespl,ngfftf,nfftf,&
     720              : & dtset%nkpt,nkxc,dtset%nspinor,dtset%nsppol,npwarr,nylmgr,occ,&
     721              : & pawfgr,pawtab,ph1d,&
     722           17 : & psps,rfpert,rhog,rhor,rmet,rprimd,ucvol,useylmgr,xred,ylm,ylmgr)
     723              : 
     724              : !Merge stationay and nonvariational contributions
     725      6485593 :  d3etot(:,:,:,:,:,:,:)=d3etot(:,:,:,:,:,:,:) + d3etot_nv(:,:,:,:,:,:,:)
     726              : 
     727              : !Real (imaginary) part of d3etot is zero for first (second) momentum derivatives
     728           17 :  if (dtset%kptopt /= 3) then
     729          131 :    do i3pert = 1, mpert
     730          120 :      if (i3pert == natom+9 ) cycle
     731          491 :      do i3dir = 1, 3
     732         4554 :        do i2pert = 1, mpert
     733        16656 :          do i2dir = 1,3
     734       161286 :            do i1pert = 1, mpert
     735       592182 :              do i1dir = 1, 3
     736       579960 :                if (blkflg(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert) == 1) then
     737          854 :                  if (i2pert /= natom+3 .and. i2pert /= natom+4) then
     738          368 :                    d3etot(1,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert) = zero
     739              :                  else
     740          486 :                    d3etot(2,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert) = zero
     741              :                  end if
     742              :                end if
     743              :              end do
     744              :            end do
     745              :          end do
     746              :        end do
     747              :      end do
     748              :    end do
     749              :  end if
     750              : 
     751              : 
     752              : !Complete missing elements using symmetry operations
     753              : ! has_strain=.false.
     754              : ! if (dtset%lw_flexo==1.or.dtset%lw_flexo==2.or.dtset%lw_flexo==4) has_strain=.true.
     755              : ! call d3lwsym(blkflg,d3etot,has_strain,indsym,mpert,natom,dtset%nsym,symrec,dtset%symrel,symrel_cart)
     756           17 :  call d3lwsym(blkflg,d3etot,indsym,mpert,natom,dtset%nsym,symrec,dtset%symrel)
     757              : 
     758              : !Deallocate global proc_distrib
     759           17 :  if(xmpi_paral==1) then
     760           17 :    ABI_FREE(mpi_enreg%proc_distrb)
     761              :  end if
     762              : 
     763              : ! Write the DDB file
     764              :  call ddb_hdr%init(dtset,psps,pawtab,&
     765              :                    dscrpt=' Note : temporary (transfer) database ',&
     766           17 :                    nblok=1,xred=xred,occ=occ)
     767              : 
     768           17 :  call ddb%init(dtset, 1, mpert, with_d3E=.true.)
     769              : 
     770           17 :  call ddb%set_omega(iblok=1, omega=dtset%rfomega)
     771              : 
     772           17 :  call ddb%set_qpt(iblok=1, qpt=dtset%qptn(1:3))
     773              : 
     774           17 :  call ddb%set_d3matr(1, d3etot, blkflg, lw=.true.)
     775              : 
     776           17 :  call ddb%write_txt(ddb_hdr, dtfil%fnameabo_ddb)
     777              : 
     778           17 :  call ddb_hdr%free()
     779           17 :  call ddb%free()
     780              : 
     781              :  !Calculate spatial-dispersion quantities in Cartesian coordinates and write
     782              :  !them in abi_out
     783          119 :  ABI_MALLOC(blkflg_car,(3,mpert,3,mpert,3,mpert))
     784          119 :  ABI_MALLOC(d3etot_car,(2,3,mpert,3,mpert,3,mpert))
     785           17 :  call lwcart(blkflg,blkflg_car,d3etot,d3etot_car,gprimd,mpert,natom,rprimd)
     786           17 :  if (me==0) then
     787           17 :    call dfptlw_out(blkflg_car,d3etot_car,dtset%lw_flexo,dtset%lw_qdrpl,dtset%lw_natopt,mpert,natom,dtset%timdisp,ucvol)
     788              :  end if
     789              : 
     790              : !Deallocate arrays
     791           17 :  ABI_FREE(atindx)
     792           17 :  ABI_FREE(atindx1)
     793           17 :  ABI_FREE(blkflg)
     794           17 :  ABI_FREE(doccde)
     795           17 :  ABI_FREE(eigen0)
     796           17 :  ABI_FREE(cg)
     797           17 :  ABI_FREE(ph1d)
     798           17 :  ABI_SFREE(ffnl)
     799           17 :  ABI_FREE(indsym)
     800           17 :  ABI_FREE(irrzon)
     801           17 :  ABI_FREE(nattyp)
     802           17 :  ABI_FREE(kg)
     803           17 :  ABI_FREE(kxc)
     804           17 :  ABI_FREE(npwarr)
     805           17 :  ABI_FREE(phnons)
     806           17 :  ABI_FREE(rhog)
     807           17 :  ABI_FREE(rhor)
     808           17 :  ABI_FREE(symrec)
     809              : ! ABI_FREE(symrel_cart)
     810           17 :  ABI_FREE(vxc)
     811           17 :  ABI_FREE(d3etot)
     812           17 :  ABI_FREE(d3etot_nv)
     813              : ! ABI_FREE(pertsy)
     814           17 :  ABI_FREE(rfpert)
     815           17 :  ABI_FREE(d3e_pert1)
     816           17 :  ABI_FREE(d3e_pert2)
     817           17 :  ABI_FREE(d3e_pert3)
     818           17 :  ABI_SFREE(pawrhoij)
     819           17 :  ABI_SFREE(nhat)
     820           17 :  ABI_SFREE(nhatgr)
     821           17 :  ABI_SFREE(ylm)
     822           17 :  ABI_SFREE(ylmgr)
     823           17 :  ABI_SFREE(blkflg_car)
     824           17 :  ABI_SFREE(d3etot_car)
     825           17 :  ABI_SFREE(ncorespl)
     826           17 :  call pawfgr_destroy(pawfgr)
     827              : 
     828              :  ! Clean the header
     829           17 :  call hdr%free()
     830              : 
     831              :  DBG_EXIT("COLL")
     832              : 
     833           34 : end subroutine longwave
     834              : !!***
     835              : 
     836              : !!****f* ABINIT/m_dfptlw_loop/dfptlw_out
     837              : !! NAME
     838              : !!  dfptlw_out
     839              : !!
     840              : !! FUNCTION
     841              : !!  Write the relevant spatial-dispersion quantities in Cartesian coordinates
     842              : !!
     843              : !! COPYRIGHT
     844              : !!  Copyright (C) 2022-2026 ABINIT group (MR)
     845              : !!  This file is distributed under the terms of the
     846              : !!  GNU General Public License, see ~abinit/COPYING
     847              : !!  or http://www.gnu.org/copyleft/gpl.txt .
     848              : !!
     849              : !! INPUTS
     850              : !!  blkflg_car(3,mpert,3,mpert,3,mpert) =flags for each element of the 3DTE
     851              : !!  d3etot_car(2,3,mpert,3,mpert,3,mpert) =array with the cartesian thir-order derivatives
     852              : !!  lw_qdrpl= flag that activates quadrupoles calculation
     853              : !!  lw_flexo= flag that activates flexoelectric tensor calculation
     854              : !!  mpert =maximum number of ipert
     855              : !!  natom = number of atoms in unit cell
     856              : !!  timdisp = if 1 write derivatives with respect to omega
     857              : !!
     858              : !! OUTPUT
     859              : !!
     860              : !! SIDE EFFECTS
     861              : !!
     862              : !! SOURCE
     863              : 
     864           17 : subroutine dfptlw_out(blkflg_car,d3etot_car,lw_flexo,lw_qdrpl,lw_natopt,mpert,natom,timdisp,ucvol)
     865              : 
     866              : !Arguments ------------------------------------
     867              : !scalars
     868              :  integer,intent(in) :: lw_flexo,lw_qdrpl,lw_natopt,mpert,natom,timdisp
     869              :  real(dp),intent(in) :: ucvol
     870              : !arrays
     871              :  integer,intent(in) :: blkflg_car(3,mpert,3,mpert,3,mpert)
     872              :  real(dp),intent(in) :: d3etot_car(2,3,mpert,3,mpert,3,mpert)
     873              : 
     874              : !Local variables-------------------------------
     875              : !scalar
     876              :  integer :: beta,delta,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert,istr
     877              : !arrays
     878              :  integer,save :: idx(18)=(/1,1,2,2,3,3,3,2,3,1,2,1,2,3,1,3,1,2/)
     879           17 :  real(dp),allocatable :: qdrp(:,:,:,:,:,:,:)
     880              :  real(dp) :: piezoci(2),piezofr(2),celastci(2)
     881              : 
     882              : ! *************************************************************************
     883              : 
     884              :  DBG_ENTER("COLL")
     885              : 
     886           17 :  i3pert=natom+8
     887           17 :  if (lw_qdrpl==1.or.lw_flexo==3.or.lw_flexo==1) then
     888           10 :    write(ab_out,'(a)')' First real-space moment of the polarization response '
     889           10 :    write(ab_out,'(a)')' to an atomic displacementatom, in cartesian coordinates,'
     890           10 :    write(ab_out,'(a)')' (1/ucvol factor not included),'
     891           10 :    write(ab_out,'(a)')' efidir   atom   atdir    qgrdir          real part        imaginary part'
     892           10 :    i1pert=natom+2
     893           40 :    do i3dir=1,3
     894          120 :      do i1dir=1,3
     895          327 :        do i2pert=1,natom
     896          918 :          do i2dir=1,3
     897          828 :            if (blkflg_car(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)==1) then
     898          621 :              write(ab_out,'(4(i5,3x),2(1x,f20.10))') i1dir,i2pert,i2dir,i3dir, &
     899          621 :            & d3etot_car(2,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert), &
     900         1242 :            & -d3etot_car(1,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)
     901              :            end if
     902              :          end do
     903              :        end do
     904              :      end do
     905           40 :      write(ab_out,*)' '
     906              :    end do
     907              : 
     908              :    !Calculate cuadrupoles (symmetrize i1dir/i3dir)
     909           70 :    ABI_MALLOC(qdrp,(2,3,mpert,3,mpert,3,mpert))
     910              :    i1pert=natom+2
     911           33 :    do i2pert=1,natom
     912          102 :      do i2dir=1,3
     913          299 :        do i1dir=1,3
     914          414 :          do i3dir=1,i1dir-1
     915          414 :            if (blkflg_car(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)==1) then
     916              :              !real part
     917              :              qdrp(1,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)=&
     918              :            & d3etot_car(2,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert) + &
     919          207 :            & d3etot_car(2,i3dir,i1pert,i2dir,i2pert,i1dir,i3pert)
     920              : 
     921              :              qdrp(1,i3dir,i1pert,i2dir,i2pert,i1dir,i3pert)=&
     922          207 :            & qdrp(1,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)
     923              : 
     924              :              !imaginary part
     925              :              qdrp(2,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)=&
     926              :            & -(d3etot_car(1,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert) + &
     927          207 :            &   d3etot_car(1,i3dir,i1pert,i2dir,i2pert,i1dir,i3pert) )
     928              : 
     929              :              qdrp(2,i3dir,i1pert,i2dir,i2pert,i1dir,i3pert)=&
     930          207 :            & qdrp(2,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)
     931              :            end if
     932              :          end do
     933          276 :          if (blkflg_car(i1dir,i1pert,i2dir,i2pert,i1dir,i3pert)==1) then
     934              :            !real part
     935              :            qdrp(1,i1dir,i1pert,i2dir,i2pert,i1dir,i3pert)=&
     936          207 :          & two*d3etot_car(2,i1dir,i1pert,i2dir,i2pert,i1dir,i3pert)
     937              : 
     938              :            !imaginary part
     939              :            qdrp(2,i1dir,i1pert,i2dir,i2pert,i1dir,i3pert)=&
     940          207 :          &-two*d3etot_car(1,i1dir,i1pert,i2dir,i2pert,i1dir,i3pert)
     941              :          end if
     942              :        end do
     943              :      end do
     944              :    end do
     945              : 
     946           10 :    write(ab_out,'(a)')' Quadrupole tensor, in cartesian coordinates,'
     947           10 :    write(ab_out,'(a)')' efidir   atom   atdir    qgrdir          real part        imaginary part'
     948           40 :    do i3dir=1,3
     949          120 :      do i1dir=1,3
     950          327 :        do i2pert=1,natom
     951          918 :          do i2dir=1,3
     952          828 :            if (blkflg_car(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)==1) then
     953          621 :              write(ab_out,'(4(i5,3x),2(1x,f20.10))') i1dir,i2pert,i2dir,i3dir, &
     954          621 :            & qdrp(1,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert), &
     955         1242 :            & qdrp(2,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)
     956              :            end if
     957              :          end do
     958              :        end do
     959              :      end do
     960           40 :      write(ab_out,*)' '
     961              :    end do
     962              : 
     963           10 :    write(ab_out,'(a)')' Electronic (clamped-ion) contribution to the piezoelectric tensor,'
     964           10 :    write(ab_out,'(a)')' in cartesian coordinates, (from sum rule of P^1 tensor)'
     965           10 :    write(ab_out,'(a)')' efidir   atdir    qgrdir        real part           imaginary part'
     966           40 :    do i3dir=1,3
     967          120 :      do i1dir=1,3
     968          390 :        do i2dir=1,3
     969          270 :          piezoci=zero
     970          891 :          do i2pert=1,natom
     971          891 :            if (blkflg_car(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)==1) then
     972          621 :              piezoci(1)=piezoci(1)+d3etot_car(2,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)
     973          621 :              piezoci(2)=piezoci(2)-d3etot_car(1,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)
     974              :            end if
     975              :          end do
     976          270 :          piezoci(1)=-piezoci(1)/ucvol
     977          270 :          piezoci(2)=-piezoci(2)/ucvol
     978          360 :          write(ab_out,'(3(i5,3x),2(1x,f20.10))') i1dir,i2dir,i3dir,piezoci(1),piezoci(2)
     979              :        end do
     980              :      end do
     981           40 :      write(ab_out,*)' '
     982              :    end do
     983              : 
     984           10 :    write(ab_out,'(a)')' Electronic (clamped-ion) contribution to the piezoelectric tensor,'
     985           10 :    write(ab_out,'(a)')' in cartesian coordinates, (from sum rule of dynamic quadrupoles)'
     986           10 :    write(ab_out,'(a)')' efidir   atdir    qgrdir        real part           imaginary part'
     987           40 :    do i3dir=1,3
     988          120 :      do i1dir=1,3
     989          390 :        do i2dir=1,3
     990          270 :          piezoci=zero
     991          891 :          do i2pert=1,natom
     992              :            if (blkflg_car(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)==1.and. &
     993          621 :                blkflg_car(i1dir,i1pert,i3dir,i2pert,i2dir,i3pert)==1.and. &
     994          270 :                blkflg_car(i2dir,i1pert,i1dir,i2pert,i3dir,i3pert)==1) then
     995              :              piezoci(1)=piezoci(1)+qdrp(1,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert) &
     996              :            &                      +qdrp(1,i1dir,i1pert,i3dir,i2pert,i2dir,i3pert) &
     997          621 :            &                      -qdrp(1,i2dir,i1pert,i1dir,i2pert,i3dir,i3pert)
     998              :              piezoci(2)=piezoci(2)+qdrp(2,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert) &
     999              :            &                      +qdrp(2,i1dir,i1pert,i3dir,i2pert,i2dir,i3pert) &
    1000          621 :            &                      -qdrp(2,i2dir,i1pert,i1dir,i2pert,i3dir,i3pert)
    1001              :            end if
    1002              :          end do
    1003          270 :          piezoci(1)=-piezoci(1)/(two*ucvol)
    1004          270 :          piezoci(2)=-piezoci(2)/(two*ucvol)
    1005          360 :          write(ab_out,'(3(i5,3x),2(1x,f20.10))') i1dir,i2dir,i3dir,piezoci(1),piezoci(2)
    1006              :        end do
    1007              :      end do
    1008           40 :      write(ab_out,*)' '
    1009              :    end do
    1010           10 :    ABI_FREE(qdrp)
    1011              :  end if
    1012              : 
    1013           17 :  if (lw_flexo==2.or.lw_flexo==1) then
    1014            3 :    write(ab_out,'(a)')' Clamped-ion flexoelectric tensor (type-II), in cartesian coordinates,'
    1015            3 :    write(ab_out,'(a)')' efidir  qgrdir  strdir1  strdir2         real part          imaginary part'
    1016            3 :    i1pert=natom+2
    1017           12 :    do i3dir=1,3
    1018           30 :      do i2pert=natom+3,natom+4
    1019           72 :        do i2dir=1,3
    1020           54 :          istr=(i2pert-natom-3)*3+i2dir
    1021           54 :          beta=idx(2*istr-1); delta=idx(2*istr)
    1022          234 :          do i1dir=1,3
    1023          216 :            if (blkflg_car(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)==1) then
    1024          162 :              write(ab_out,'(4(i5,3x),2(1x,f20.10))') i1dir,i3dir,beta,delta, &
    1025          162 :            & d3etot_car(1,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)/ucvol, &
    1026          324 :            & d3etot_car(2,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)/ucvol
    1027              :            end if
    1028              :          end do
    1029              :        end do
    1030           27 :        write(ab_out,*)' '
    1031              :      end do
    1032              :    end do
    1033              :  end if
    1034              : 
    1035           17 :  if (lw_flexo==3.or.lw_flexo==1) then
    1036            3 :    write(ab_out,'(a)')' 1st real-space moment of IFCs, in cartesian coordinates,'
    1037            3 :    write(ab_out,'(a)')' iatdir   iatom    jatdir   jatom    qgrdir           real part          imaginary part'
    1038           12 :    do i3dir=1,3
    1039           27 :      do i1pert=1,natom
    1040           81 :        do i1dir=1,3
    1041          180 :          do i2pert=1,natom
    1042          486 :            do i2dir=1,3
    1043          432 :              if (blkflg_car(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)==1) then
    1044          324 :                write(ab_out,'(5(i5,4x),2(1x,f20.10))') i1dir,i1pert,i2dir,i2pert,i3dir, &
    1045          324 :              & -d3etot_car(2,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert),&
    1046          648 :              &  d3etot_car(1,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)
    1047              :              end if
    1048              :            end do
    1049              :          end do
    1050              :        end do
    1051              :      end do
    1052           12 :      write(ab_out,*)' '
    1053              :    end do
    1054              : 
    1055            3 :    write(ab_out,'(a)')' Piezoelectric force-response tensor, in cartesian coordinates '
    1056            3 :    write(ab_out,'(a)')' (from sum rule of 1st moment of IFCs),'
    1057            3 :    write(ab_out,'(a)')' (for non-vanishing forces in the cell it lacks an improper contribution),'
    1058            3 :    write(ab_out,'(a)')' iatom   iatddir  jatddir   qgrdir           real part          imaginary part'
    1059           12 :    do i3dir=1,3
    1060           27 :      do i1pert=1,natom
    1061           81 :        do i1dir=1,3
    1062          234 :          do i2dir=1,3
    1063          162 :            piezofr=zero
    1064          486 :            do i2pert=1,natom
    1065          486 :              if (blkflg_car(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)==1) then
    1066          324 :                piezofr(1)=piezofr(1)-d3etot_car(2,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)
    1067          324 :                piezofr(2)=piezofr(2)+d3etot_car(1,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)
    1068              :              end if
    1069              :            end do
    1070          162 :            write(ab_out,'(4(i5,4x),2(1x,f20.10))') i1pert,i1dir,i2dir,i3dir, &
    1071          378 :          & piezofr(1), piezofr(2)
    1072              :          end do
    1073              :        end do
    1074              :      end do
    1075           12 :      write(ab_out,*)' '
    1076              :    end do
    1077              :  end if
    1078              : 
    1079           17 :  if (lw_flexo==4.or.lw_flexo==1) then
    1080            3 :    write(ab_out,'(a)')' Clamped-ion flexoelectric force-response tensor (type-II),  in cartesian coordinates,'
    1081            3 :    write(ab_out,'(a)')'  atom   atdir   qgrdir  strdir1 strdir2          real part          imaginary part'
    1082           12 :    do i3dir=1,3
    1083           30 :      do i1pert=1,natom
    1084           81 :        do i1dir=1,3
    1085          162 :          do i2pert=natom+3, natom+4
    1086          486 :            do i2dir=1,3
    1087          324 :              istr=(i2pert-natom-3)*3+i2dir
    1088          324 :              beta=idx(2*istr-1); delta=idx(2*istr)
    1089          432 :              if (blkflg_car(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)==1) then
    1090          324 :                write(ab_out,'(5(i5,3x),2(1x,f20.10))') i1pert,i1dir,i3dir,beta,delta, &
    1091          324 :              & d3etot_car(1,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert),&
    1092          648 :              & d3etot_car(2,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)
    1093              :              end if
    1094              :            end do
    1095              :          end do
    1096           72 :          write(ab_out,*)' '
    1097              :        end do
    1098              :      end do
    1099              :    end do
    1100              : 
    1101              : 
    1102            3 :    write(ab_out,'(a)')' Clamped-ion elastic tensor, in cartesian coordinates '
    1103            3 :    write(ab_out,'(a)')' (from sum rule of clamped-ion flexoelectric force-response tensor),'
    1104            3 :    write(ab_out,'(a)')' (for stressed cells it lacks an improper contribution),'
    1105            3 :    write(ab_out,'(a)')' atdir   qgrdir  strdir1  strdir2         real part          imaginary part'
    1106           12 :    do i1dir=1,3
    1107           30 :      do i3dir=1,i1dir
    1108           54 :        do i2pert=natom+3, natom+4
    1109          162 :          do i2dir=1,3
    1110          108 :            istr=(i2pert-natom-3)*3+i2dir
    1111          108 :            beta=idx(2*istr-1); delta=idx(2*istr)
    1112          108 :            celastci=zero
    1113          324 :            do i1pert=1,natom
    1114          324 :              if (blkflg_car(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)==1) then
    1115          216 :                celastci(1)=celastci(1)+d3etot_car(1,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)
    1116          216 :                celastci(2)=celastci(2)+d3etot_car(2,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)
    1117              :              end if
    1118              :            end do
    1119          108 :            write(ab_out,'(4(i5,3x),2(1x,f20.10))') i1dir,i3dir,beta,delta, &
    1120          252 :          & celastci(1)/ucvol,celastci(2)/ucvol
    1121              :          end do
    1122              :        end do
    1123           27 :        write(ab_out,*)' '
    1124              :      end do
    1125              :    end do
    1126              :  end if
    1127              : 
    1128           17 :  if (lw_natopt==1) then
    1129            1 :    write(ab_out,'(a)')' Natural optical activity tensor, in cartesian coordinates,'
    1130            1 :    write(ab_out,'(a)')' (1/ucvol factor not included),'
    1131            1 :    write(ab_out,'(a)')' efidir1   efidir2   qgrdir          real part          imaginary part'
    1132            1 :    i1pert=natom+2
    1133            1 :    i2pert=natom+2
    1134            4 :    do i3dir=1,3
    1135           12 :      do i1dir=1,3
    1136           39 :        do i2dir=1,3
    1137           36 :          if (blkflg_car(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)==1) then
    1138           27 :            write(ab_out,'(3(i5,3x),2(1x,f20.10))') i1dir,i2dir,i3dir, &
    1139           27 :          & -four*pi*d3etot_car(2,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert), &
    1140           54 :          &  four*pi*d3etot_car(1,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)
    1141              :          end if
    1142              :        end do
    1143              :      end do
    1144            4 :      write(ab_out,*)' '
    1145              :    end do
    1146              :  end if
    1147              : 
    1148           17 :  if (timdisp==1) then
    1149            6 :    i3pert=natom+9
    1150            6 :    i3dir=1
    1151            6 :    write(ab_out,'(a)')' Frequency derivative of second-order energies, in cartesian coordinates'
    1152            6 :    write(ab_out,'(a)')'     j1       j2                    matrix elementi'
    1153            6 :    write(ab_out,'(a)')'  dir pert dir pert           real part       imaginary part'
    1154          128 :    do i1pert=1,mpert
    1155          494 :      do i1dir=1,3
    1156         8186 :        do i2pert=1,mpert
    1157        31158 :          do i2dir=1,3
    1158        30792 :            if (blkflg_car(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)==1) then
    1159           30 :              write(ab_out,'(2(i4,i5),2(1x,f20.10))')i1dir,i1pert,i2dir,i2pert,&
    1160           30 :            & d3etot_car(1,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert), &
    1161           60 :            & d3etot_car(2,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)
    1162              :            end if
    1163              :          end do
    1164              :        end do
    1165              :      end do
    1166              :    end do
    1167              :  end if
    1168              : 
    1169              :  DBG_EXIT("COLL")
    1170              : 
    1171           17 : end subroutine dfptlw_out
    1172              : !!***
    1173              : 
    1174              : end module m_longwave
    1175              : !!***
        

Generated by: LCOV version 2.3-1