LCOV - code coverage report
Current view: top level - src/77_ddb - m_ddb_flexo.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 78.7 % 703 553
Test Date: 2026-09-21 19:39:32 Functions: 100.0 % 6 6

            Line data    Source code
       1              : !!****m* ABINIT/m_ddb_flexo
       2              : !! NAME
       3              : !!  m_ddb_flexo
       4              : !!
       5              : !! FUNCTION
       6              : !!  FIXME: add description.
       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_ddb_flexo
      25              : 
      26              :  use defs_basis
      27              :  use m_abicore
      28              :  use m_profiling_abi
      29              :  use m_errors
      30              : 
      31              :  use m_fstrings,       only : itoa,sjoin
      32              :  use m_ddb_hdr
      33              :  use m_ddb
      34              :  use m_crystal,        only : crystal_t
      35              :  use m_dynmat,       only : asria_corr,cart39
      36              : 
      37              :  implicit none
      38              : 
      39              :  private
      40              : 
      41              :  public :: ddb_flexo
      42              :  public :: ddb_phi1
      43              : ! *************************************************************************
      44              : 
      45              : contains
      46              : !!***
      47              : 
      48              : !!****f* ABINIT/m_ddb_flexo/ddb_flexo
      49              : !! NAME
      50              : !!  ddb_flexo
      51              : !!
      52              : !! FUNCTION
      53              : !! Get all the contributions to the flexoelectric tensor
      54              : !!
      55              : !! INPUTS
      56              : !!  asr= if /=0 acustic sume rule is imposed on the dynamical matrix
      57              : !!  d2asr(2,3,natom,3,natom)=ASR-correction
      58              : !!  ddb<type(ddb_type)>=2nd order derivative database.
      59              : !!  ddb_lw<type(ddb_type)>=Long wave 3rd order derivative database.
      60              : !!  ddb_version = 8 digit integer giving date. To mantain compatibility with old DDB files.
      61              : !!  Crystal<type(crystal_t)>=Crystal structure parameters
      62              : !!  filnamddb = name of the ddb file
      63              : !!  flexoflg=  1 -> Computes all contributions to FxE
      64              : !!             2 -> Computes electronic (clamped ion) contribution to FxE
      65              : !!             3 -> Computes mixed contribution to FxE
      66              : !!             4 -> Computes lattice contribution to FxE
      67              : !!  prtvol= if > 1 print all individual quantities of the lattice contribution FxE
      68              : !!  zeff(3,3,natom)= Born Effective charges
      69              : !!
      70              : !! OUTPUT
      71              : !!
      72              : !! SIDE EFFECTS
      73              : !!
      74              : !! NOTES
      75              : !!
      76              : !! SOURCE
      77              : 
      78            2 : subroutine ddb_flexo(asr,d2asr,ddb,ddb_lw,ddb_version,crystal,filnamddb,flexoflg,prtvol,zeff)
      79              : 
      80              : !Arguments ------------------------------------
      81              : !scalars
      82              :  integer,intent(in) :: ddb_version
      83              :  integer , intent(in)  :: asr,flexoflg,prtvol
      84              :  class(ddb_type),intent(in) :: ddb,ddb_lw
      85              :  type(crystal_t),intent(in) :: crystal
      86              :  character(len=fnlen) :: filnamddb
      87              : !arrays
      88              :  real(dp),intent(in) :: d2asr(2,3,ddb%natom,3,ddb%natom)
      89              :  real(dp),intent(in) :: zeff(3,3,ddb%natom)
      90              : 
      91              : !Local variables-------------------------------
      92              :  integer :: elfd,iblok,ivar,jblok,kblok,lblok,lwsym,qvecd
      93              :  logical :: intstrn_only,iwrite
      94              :  character(len=500) :: msg
      95              : 
      96              : !arrays
      97              :  integer,parameter :: alpha(6)=(/1,2,3,2,1,1/),beta(6)=(/1,2,3,3,3,2/)
      98              :  integer :: rfelfd(4),rfphon(4),rfstrs(4)
      99              :  integer :: rfqvec(4)
     100              :  real(dp) :: qphnrm(3),qphon(3,3)
     101              :  real(dp) :: ciflexo(3,3,3,3)
     102            4 :  real(dp) :: intstrn(3,3,3,ddb%natom)
     103            4 :  real(dp) :: piezofr(3,ddb%natom,3,3)
     104              :  real(dp) :: lattflexo(3,3,3,3)
     105              :  real(dp) :: mixflexo(3,3,3,3)
     106            4 :  real(dp) :: pol1(3,3,3,ddb%natom)
     107            4 :  real(dp) :: psinvdm(3*ddb%natom,3*ddb%natom)
     108              :  real(dp) :: totflexo(3,3,3,3)
     109              :  character(len=2) :: voigt(9)=(/'xx','yy','zz','yz','xz','xy','zy','zx','yx'/)
     110              : 
     111              : ! *************************************************************************
     112              : 
     113              :  DBG_ENTER("COLL")
     114              : 
     115              : ! First get the clamped-ion flexoelectric tensor
     116            2 :  ciflexo(:,:,:,:)=zero
     117            2 :  if (flexoflg==1.or.flexoflg==2) then
     118              : 
     119              :    rfphon(:)=0
     120            2 :    rfelfd(:)=0
     121            2 :    rfstrs(:)=0
     122            2 :    rfqvec(:)=0
     123              : 
     124              :    ! Look for the Gamma Block in the DDB
     125            2 :    qphon(:,:)=zero
     126            8 :    qphnrm(:)=one
     127            2 :    rfphon(:)=0
     128            2 :    rfelfd(1)=2
     129            2 :    rfstrs(2)=3
     130            2 :    rfqvec(3)=1
     131              : 
     132            2 :    write(msg, '(2a)' ) ch10," Extract the electronic flexoelectric coeficients from 3DTE"
     133            2 :    call wrtout(std_out,msg,'COLL')
     134            2 :    call ddb_lw%get_block(iblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,BLKTYP_d3E_lw,rfqvec=rfqvec)
     135              : 
     136            2 :    if (iblok == 0) then
     137            0 :      call wrtout(std_out, "  ")
     138            0 :      call wrtout(std_out, "--- !WARNING")
     139            0 :      call wrtout(std_out, sjoin("- Cannot find clamped ion FxE tensor in DDB file:", filnamddb))
     140            0 :      call wrtout(std_out, "  flexoflag=1 or 2 requires the DDB file to include the corresponding long wave 3rd derivatives")
     141              :    else
     142            2 :      call dtciflexo(ddb_lw%val(:,:,iblok),ddb_version,ddb%mpert,ddb%natom,ciflexo,crystal%ucvol)
     143              :    end if
     144              : 
     145              :  end if
     146              : 
     147              : ! Then get the mixed contribution to the flexoelectric tensor
     148              :  !Activate the calculation of internal strain necessary for lattice mediated contribution.
     149            2 :  intstrn_only=.false.;if (flexoflg==4) intstrn_only=.true.
     150            2 :  mixflexo(:,:,:,:)=zero
     151            2 :  if (flexoflg==1.or.flexoflg==3.or.intstrn_only) then
     152              : 
     153              :    ! Extract the P^(1) tensor from the DDB
     154            2 :    if (.not.intstrn_only) then
     155            2 :      lwsym=0
     156            2 :      iblok = ddb_lw%get_quadrupoles(ddb_version,lwsym,BLKTYP_d3E_lw,pol1)
     157              :    end if
     158              : 
     159            2 :    rfphon(:)=0
     160            2 :    rfelfd(:)=0
     161            2 :    rfstrs(:)=0
     162            2 :    rfqvec(:)=0
     163              : 
     164              :    ! Look for the Gamma Block of the Phi^(1) tensor in the DDB
     165            2 :    qphon(:,:)=zero
     166            8 :    qphnrm(:)=one
     167            2 :    rfphon(1)=1
     168            2 :    rfphon(2)=1
     169            2 :    rfqvec(3)=1
     170              : 
     171            2 :    write(msg, '(2a)' ) ch10," Extract the Phi^(1) coeficients from 3DTE"
     172            2 :    call wrtout(std_out,msg,'COLL')
     173            2 :    call ddb_lw%get_block(iblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,BLKTYP_d3E_lw,rfqvec=rfqvec)
     174              : 
     175            2 :    if (iblok == 0) then
     176            0 :      call wrtout(std_out, "  ")
     177            0 :      call wrtout(std_out, "--- !WARNING")
     178            0 :      call wrtout(std_out, sjoin("- Cannot find Phi^(1) tensor in DDB file:", filnamddb))
     179            0 :      call wrtout(std_out, "  flexoflag=1 or 3 requires the DDB file to include the corresponding long wave 3rd derivatives")
     180              :    end if
     181              : 
     182              :    ! Look for th block that contains the forces
     183            2 :    qphon(:,:)=zero
     184            8 :    qphnrm(:)=one
     185            2 :    rfphon(:)=0
     186            2 :    rfphon(4)=1
     187              : 
     188            2 :    write(msg, '(2a)' ) ch10," Extract the forces from 1DTE"
     189            2 :    call wrtout(std_out,msg,'COLL')
     190            2 :    call ddb%get_block(kblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,4)
     191              : 
     192            2 :    if (kblok == 0) then
     193            0 :      call wrtout(std_out, "  ")
     194            0 :      call wrtout(std_out, "--- !WARNING")
     195            0 :      call wrtout(std_out, sjoin("- Cannot find forces in DDB file:", filnamddb))
     196            0 :      call wrtout(std_out, "  If there are nonzero residual atomic forces on the structure")
     197            0 :      call wrtout(std_out, "  flexoflag=1 or 3 will produce an improper piezoelectric force response tensor")
     198            0 :      call wrtout(std_out, "  and a wrong value for the mixed contribution to the flexoelectric tensor")
     199              :    end if
     200              : 
     201              :    ! Look for the Gamma Block of the dynamical matrix in the DDB
     202            2 :    qphon(:,:)=zero
     203            8 :    qphnrm(:)=one
     204            2 :    rfphon(:)=0
     205            6 :    rfphon(1:2)=1
     206              : 
     207            2 :    write(msg, '(2a)' ) ch10," Extract the Dynamical Matrix from 2DTE"
     208            2 :    call wrtout(std_out,msg,'COLL')
     209            2 :    call ddb%get_block(jblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,1)
     210              : 
     211            2 :    if (jblok == 0) then
     212            0 :      call wrtout(std_out, "  ")
     213            0 :      call wrtout(std_out, "--- !WARNING")
     214            0 :      call wrtout(std_out, sjoin("- Cannot find Gamma point Dynamical Matrix in DDB file:", filnamddb))
     215            0 :      call wrtout(std_out, "  flexoflag=1 or 3 requires the DDB file to include the corresponding 2nd derivatives")
     216              :    end if
     217              : 
     218            2 :    if (iblok/=0.and.jblok/=0) then
     219              :      call dtmixflexo(asr,d2asr,ddb%val(:,:,kblok),ddb%val(:,:,jblok),ddb_lw%val(:,:,iblok),ddb_version,crystal%gprimd,&
     220            2 :    & intstrn,intstrn_only,mixflexo,ddb%mpert,ddb%natom,piezofr,pol1,psinvdm,crystal%rprimd,crystal%ucvol)
     221              :    end if
     222              : 
     223              :  end if
     224              : 
     225              : ! Finally get the lattice mediated contribution to the flexoelectric tensor
     226            2 :  lattflexo(:,:,:,:)=zero
     227            2 :  if (flexoflg==1.or.flexoflg==4) then
     228              : 
     229            2 :    rfphon(:)=0
     230            2 :    rfelfd(:)=0
     231            2 :    rfstrs(:)=0
     232            2 :    rfqvec(:)=0
     233              : 
     234              :    ! Look for the Gamma Block of the Phi^(1) tensor in the DDB
     235            2 :    qphon(:,:)=zero
     236            8 :    qphnrm(:)=one
     237            2 :    rfphon(1)=1
     238            2 :    rfphon(2)=1
     239            2 :    rfqvec(3)=1
     240              : 
     241            2 :    write(msg, '(2a)' ) ch10," Extract the Phi^(1) coeficients from 3DTE"
     242            2 :    call wrtout(std_out,msg,'COLL')
     243            2 :    call ddb_lw%get_block(iblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,BLKTYP_d3E_lw,rfqvec=rfqvec)
     244              : 
     245            2 :    if (iblok == 0) then
     246            0 :      call wrtout(std_out, "  ")
     247            0 :      call wrtout(std_out, "--- !WARNING")
     248            0 :      call wrtout(std_out, sjoin("- Cannot find Phi^(1) tensor in DDB file:", filnamddb))
     249            0 :      call wrtout(std_out, "  flexoflag=1 or 4 requires the DDB file to include the corresponding long wave 3rd derivatives")
     250              :    end if
     251              : 
     252              :    ! Look for the Gamma Block of the flexoelectric force response tensor in the DDB
     253            2 :    qphon(:,:)=zero
     254            8 :    qphnrm(:)=one
     255            2 :    rfphon(:)=0
     256            2 :    rfphon(1)=1
     257            2 :    rfstrs(2)=3
     258              :    rfqvec(3)=1
     259              : 
     260            2 :    write(msg, '(2a)' ) ch10," Extract the FxE force response coeficients from 3DTE"
     261            2 :    call wrtout(std_out,msg,'COLL')
     262            2 :    call ddb_lw%get_block(jblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,BLKTYP_d3E_lw,rfqvec=rfqvec)
     263              : 
     264            2 :    if (jblok == 0) then
     265            0 :      call wrtout(std_out, "  ")
     266            0 :      call wrtout(std_out, "--- !WARNING")
     267            0 :      call wrtout(std_out, sjoin("- Cannot find FxE force response tensor in DDB file:", filnamddb))
     268            0 :      call wrtout(std_out, "  flexoflag=1 or 4 requires the DDB file to include the corresponding long wave 3rd derivatives")
     269              :    end if
     270              : 
     271              :    ! Look for the stress tensor in the DDB
     272            2 :    qphon(:,:)=zero
     273            8 :    qphnrm(:)=one
     274            2 :    rfphon(:)=0
     275            2 :    rfstrs(:)=0
     276            2 :    rfqvec(:)=0
     277            2 :    rfstrs(4)=3
     278              : 
     279            2 :    write(msg, '(2a)' ) ch10," Extract the stress tensor from 1DTE"
     280            2 :    call wrtout(std_out,msg,'COLL')
     281            2 :    call ddb%get_block(lblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,4)
     282              : 
     283            2 :    if (lblok == 0) then
     284            0 :      call wrtout(std_out, "  ")
     285            0 :      call wrtout(std_out, "--- !WARNING")
     286            0 :      call wrtout(std_out, sjoin("- Cannot find stress tensor in DDB file:", filnamddb))
     287            0 :      call wrtout(std_out, "  flexoflag=1 or 4 requires the DDB file to include the corresponding 2nd derivatives")
     288            0 :      call wrtout(std_out, "  to compute the Lagrange Elastic Tensor ")
     289              :    end if
     290              : 
     291            2 :    if (iblok/=0.and.jblok/=0) then
     292              :      call dtlattflexo(ddb%amu,ddb%val(:,:,lblok),ddb_lw%val(:,:,jblok),ddb_lw%val(:,:,iblok),ddb_version,&
     293            2 :    & intstrn,lattflexo,ddb%mpert,ddb%natom,crystal%ntypat,piezofr,prtvol,psinvdm,crystal%typat,crystal%ucvol,zeff)
     294              :    end if
     295              :  end if
     296              : 
     297              : !Merge the three contributions and print the total FxE tensor
     298          242 :  totflexo(:,:,:,:)=ciflexo(:,:,:,:)+mixflexo(:,:,:,:)+lattflexo(:,:,:,:)
     299              : 
     300            2 :  iwrite = ab_out > 0
     301            2 :  if (iwrite) then
     302            2 :    write(msg,'(3a)')ch10,' TOTAL flexoelectric tensor (units= nC/m) ',ch10
     303            6 :    call wrtout([ab_out,std_out],msg,'COLL')
     304            2 :    write(msg,*)'           xx          yy          zz          yz          xz          xy'
     305            6 :    call wrtout([ab_out,std_out],msg,'COLL')
     306           14 :    do ivar=1,6
     307           12 :      elfd=alpha(ivar)
     308           12 :      qvecd=beta(ivar)
     309           12 :      write(msg,'(3x,a2,6f12.6)') voigt(ivar),totflexo(elfd,qvecd,1,1),totflexo(elfd,qvecd,2,2),totflexo(elfd,qvecd,3,3),&
     310           24 :                            totflexo(elfd,qvecd,2,3),totflexo(elfd,qvecd,1,3),totflexo(elfd,qvecd,1,2)
     311           38 :      call wrtout([ab_out,std_out],msg,'COLL')
     312              :    end do
     313            8 :    do ivar=4,6
     314            6 :      elfd=beta(ivar)
     315            6 :      qvecd=alpha(ivar)
     316            6 :      write(msg,'(3x,a2,6f12.6)') voigt(ivar+3),totflexo(elfd,qvecd,1,1),totflexo(elfd,qvecd,2,2),totflexo(elfd,qvecd,3,3),&
     317           12 :                            totflexo(elfd,qvecd,2,3),totflexo(elfd,qvecd,1,3),totflexo(elfd,qvecd,1,2)
     318           20 :      call wrtout([ab_out,std_out],msg,'COLL')
     319              :    end do
     320              :  end if
     321              : 
     322              : 
     323              :  DBG_EXIT("COLL")
     324              : 
     325            2 : end subroutine ddb_flexo
     326              : !!***
     327              : 
     328              : !!****f* m_ddb/dtciflexo
     329              : !! NAME
     330              : !! dtciflexo
     331              : !!
     332              : !! FUNCTION
     333              : !! Reads the Clamped Ion Flexoelectric Tensor
     334              : !! in the Gamma Block coming from the Derivative Data Base
     335              : !! (long wave third-order derivatives).
     336              : !!
     337              : !! INPUTS
     338              : !! blkval(2,3*mpert*3*mpert*3*mpert)= matrix of third-order energies
     339              : !! mpert =maximum number of ipert
     340              : !! natom= number of atoms in unit cell
     341              : !! ddb_version = 8 digit integer giving date. To mantain compatibility with old DDB files.
     342              : !! ucvol= unit cell volume
     343              : !!
     344              : !! OUTPUT
     345              : !! ciflexo(3,3,3,3) = type-II Clamped Ion Flexoelectric Tensor
     346              : !!
     347              : !! SOURCE
     348              : 
     349            2 : subroutine dtciflexo(blkval,ddb_version,mpert,natom,ciflexo,ucvol)
     350              : 
     351              : !Arguments -------------------------------
     352              : !scalars
     353              :  integer,intent(in) :: ddb_version,mpert,natom
     354              :  real(dp),intent(in) :: ucvol
     355              : !arrays
     356              :  real(dp),intent(in) :: blkval(2,3*mpert*3*mpert*3*mpert)
     357              :  real(dp),intent(out) :: ciflexo(3,3,3,3)
     358              : 
     359              : !Local variables -------------------------
     360              : !scalars
     361              :  integer,parameter :: cvrsio8=20100401
     362              :  integer :: elfd,istrs,ivarA,ri,strsd,strsd1,strsd2,strst,qvecd
     363              :  logical :: iwrite
     364              :  real(dp) :: fac
     365              :  character(len=500) :: msg
     366              :  real(dp),parameter :: confac=e_Cb/Bohr_meter*1.d9
     367              : !arrays
     368              :  integer,parameter :: alpha(6)=(/1,2,3,2,1,1/),beta(6)=(/1,2,3,3,3,2/)
     369            4 :  real(dp) :: d3cart(2,3,mpert,3,mpert,3,mpert)
     370              :  character(len=2) :: voigt(9)=(/'xx','yy','zz','yz','xz','xy','zy','zx','yx'/)
     371              : 
     372              : ! *********************************************************************
     373              : 
     374              :  DBG_ENTER("COLL")
     375              : 
     376       375606 :  d3cart(1,:,:,:,:,:,:) = reshape(blkval(1,:),shape = (/3,mpert,3,mpert,3,mpert/))
     377       375606 :  d3cart(2,:,:,:,:,:,:) = reshape(blkval(2,:),shape = (/3,mpert,3,mpert,3,mpert/))
     378              : 
     379              : !Define the factors to apply if DDB file has been created with the old version of
     380              : !the longwave driver.
     381            2 :  if (ddb_version <= cvrsio8) then
     382            1 :    fac=-two/ucvol
     383            1 :    ri=2
     384              :  else
     385            1 :    fac=one/ucvol
     386            1 :    ri=1
     387              :  end if
     388              : 
     389              : !Extraction of the clamped-ion flexoelectric coeficients
     390            8 :  do qvecd=1,3
     391           44 :    do istrs=1,6
     392           36 :      strsd1=alpha(istrs)
     393           36 :      strsd2=beta(istrs)
     394           36 :      strst=natom+3; if (istrs>3) strst=natom+4
     395           18 :      strsd=istrs; if (istrs>3) strsd=istrs-3
     396          150 :      do elfd=1,3
     397          108 :        ciflexo(elfd,qvecd,strsd1,strsd2)=fac*d3cart(ri,elfd,natom+2,strsd,strst,qvecd,natom+8)*confac
     398          144 :        if (istrs>3) ciflexo(elfd,qvecd,strsd2,strsd1)=ciflexo(elfd,qvecd,strsd1,strsd2)
     399              :      end do
     400              :    end do
     401              :  end do
     402              : 
     403              : !Print results
     404            2 :  iwrite = ab_out > 0
     405            2 :  if (iwrite) then
     406            2 :    write(msg,'(3a)')ch10,' Type-II electronic (clamped ion) flexoelectric tensor (units= nC/m) ',ch10
     407            6 :    call wrtout([ab_out,std_out],msg,'COLL')
     408            2 :    write(msg,*)'           xx          yy          zz          yz          xz          xy'
     409            6 :    call wrtout([ab_out,std_out],msg,'COLL')
     410           14 :    do ivarA=1,6
     411           12 :      elfd=alpha(ivarA)
     412           12 :      qvecd=beta(ivarA)
     413           12 :      write(msg,'(3x,a2,6f12.6)') voigt(ivarA), ciflexo(elfd,qvecd,1,1),ciflexo(elfd,qvecd,2,2), &
     414           12 :                                  ciflexo(elfd,qvecd,3,3), ciflexo(elfd,qvecd,2,3), &
     415           24 :                                  ciflexo(elfd,qvecd,1,3),ciflexo(elfd,qvecd,1,2)
     416           38 :      call wrtout([ab_out,std_out],msg,'COLL')
     417              :    end do
     418            8 :    do ivarA=4,6
     419            6 :      elfd=beta(ivarA)
     420            6 :      qvecd=alpha(ivarA)
     421            6 :      write(msg,'(3x,a2,6f12.6)') voigt(ivarA+3), ciflexo(elfd,qvecd,1,1),ciflexo(elfd,qvecd,2,2), &
     422            6 :                                  ciflexo(elfd,qvecd,3,3), ciflexo(elfd,qvecd,2,3), &
     423           12 :                                  ciflexo(elfd,qvecd,1,3),ciflexo(elfd,qvecd,1,2)
     424           20 :      call wrtout([ab_out,std_out],msg,'COLL')
     425              :    end do
     426              :  end if
     427              : 
     428              :  DBG_EXIT("COLL")
     429              : 
     430            2 :  end subroutine dtciflexo
     431              : !!***
     432              : 
     433              : !!****f* m_ddb/dtmixflexo
     434              : !! NAME
     435              : !! dtmixflexo
     436              : !!
     437              : !! FUNCTION
     438              : !! Reads the P^(1) and Phi^(1) tensors
     439              : !! in the Gamma Block coming from the Derivative Data Base
     440              : !! (long wave third-order derivatives). And computes the mixed
     441              : !! contribution to the flexoelectric tensor.
     442              : !!
     443              : !! INPUTS
     444              : !! asr= if /=0 acustic sume rule is imposed on the dynamical matrix
     445              : !! d2asr(2,3,natom,3,natom)=ASR-correction
     446              : !! blkval1d(2,3,mpert,3,mpert)= 1st derivative wrt atom displacements (at least)
     447              : !! blkval2d(2,3,mpert,3,mpert)= 2nd derivatives wrt two atom displacements (at least)
     448              : !! blkval(2,3*mpert*3*mpert*3*mpert)= matrix of third-order energies for Phi^(1) tensor
     449              : !! ddb_version = 8 digit integer giving date. To mantain compatibility with old DDB files.
     450              : !! gprimd(3,3)= basis vectors in the reciprocal space
     451              : !! intstrn_only= activates only the calculation of the internal strain tensor
     452              : !! mpert =maximum number of ipert
     453              : !! natom= number of atoms in unit cell
     454              : !! piezofr(3,natom,3,3)= piezoelectric force response tensor
     455              : !! pol1(3,3,3,natom)= tensor with the polarization induced by an atomic displacement (P^(1))
     456              : !! rprimd(3,3)= basis vectors in the real space
     457              : !! ucvol= unit cell volume
     458              : !!
     459              : !! OUTPUT
     460              : !! mixflexo(3,3,3,3) = type-II mixed contribution to the Flexoelectric Tensor
     461              : !! intstrn(3,3,3,natom) = relaxed-ion internal strain tensor
     462              : !! psinvdm(3*natom,3*natom) = pseudo inverse of dynamical matrix
     463              : !!
     464              : !! SOURCE
     465              : 
     466            2 : subroutine dtmixflexo(asr,d2asr,blkval1d,blkval2d,blkval,ddb_version,gprimd,intstrn,intstrn_only, &
     467            2 :               & mixflexo,mpert,natom,piezofr,pol1,psinvdm,rprimd,ucvol)
     468              : 
     469              : !Arguments -------------------------------
     470              : !scalars
     471              :  integer,intent(in) :: asr,ddb_version,mpert,natom
     472              :  real(dp),intent(in) :: ucvol
     473              :  logical,intent(in) :: intstrn_only
     474              : !arrays
     475              :  real(dp),intent(in) :: d2asr(2,3,mpert,3,mpert)
     476              :  real(dp),intent(in) :: blkval1d(2,3,mpert,3,mpert)
     477              :  real(dp),intent(in) :: blkval2d(2,3,mpert,3,mpert)
     478              :  real(dp),intent(in) :: blkval(2,3*mpert*3*mpert*3*mpert)
     479              :  real(dp),intent(in) :: gprimd(3,3)
     480              :  real(dp),intent(out) :: intstrn(3,3,3,natom)
     481              :  real(dp),intent(out) :: piezofr(3,natom,3,3)
     482              :  real(dp),intent(inout) :: pol1(3,3,3,natom)
     483              :  real(dp),intent(out) :: psinvdm(3*natom,3*natom)
     484              :  real(dp),intent(in) :: rprimd(3,3)
     485              :  real(dp),intent(out) :: mixflexo(3,3,3,3)
     486              : 
     487              : !Local variables -------------------------
     488              : !scalars
     489              :  integer,parameter :: cvrsio8=20100401
     490              :  integer :: elfd,iat,iatd,ivar,jat,jatd,jvar,katd,qvecd,qvecd2
     491              :  logical :: iwrite
     492              :  real(dp),parameter :: confac=e_Cb/Bohr_meter*1.d9
     493              :  real(dp) :: fac
     494              :  character(len=500) :: msg
     495              : !arrays
     496              :  integer,parameter :: alpha(6)=(/1,2,3,2,1,1/),beta(6)=(/1,2,3,3,3,2/)
     497            4 :  real(dp) :: d3cart(2,3,mpert,3,mpert,3,mpert)
     498            4 :  real(dp) :: redforces(3,natom),forces(3,natom)
     499            4 :  real(dp) :: phi1(3,natom,3,natom,3)
     500              :  integer :: flg1(3),flg2(3)
     501              :  real(dp) :: vec1(3),vec2(3)
     502              :  character(len=2) :: voigt(9)=(/'xx','yy','zz','yz','xz','xy','zy','zx','yx'/)
     503              : 
     504              : ! *********************************************************************
     505              : 
     506              :  DBG_ENTER("COLL")
     507              : 
     508       375606 :  d3cart(1,:,:,:,:,:,:) = reshape(blkval(1,:),shape = (/3,mpert,3,mpert,3,mpert/))
     509       375606 :  d3cart(2,:,:,:,:,:,:) = reshape(blkval(2,:),shape = (/3,mpert,3,mpert,3,mpert/))
     510              : 
     511              : !P^(1) lacks the 1/ucvol factor
     512          242 :  pol1=pol1/ucvol
     513              : 
     514              : !Define the factors to apply if DDB file has been created with the old version of
     515              : !the longwave driver.
     516            2 :  if (ddb_version <= cvrsio8) then
     517              :    fac=-two
     518              :  else
     519            1 :    fac=-one
     520              :  end if
     521              : 
     522              : !Extraction of Phi^(1) tensor
     523              :  phi1(:,:,:,:,:) = fac*RESHAPE(d3cart(2,1:3,1:natom,1:3,1:natom,1:3,natom+8), &
     524          812 :                                & SHAPE=[3,natom,3,natom,3])
     525              : 
     526              : !Extraction of the forces and conversion to cartesian coordinates
     527              : !to acount for the improper contribution
     528           26 :  redforces(:,:)=-blkval1d(1,1:3,1:natom,1,1)
     529              : 
     530           26 :  forces(:,:)=redforces(:,:)
     531            8 :  flg1(:)=1
     532            8 :  do iat=1,natom
     533           24 :    vec1(:)=forces(:,iat)
     534            6 :    call cart39(flg1,flg2,gprimd,iat,natom,rprimd,vec1,vec2)
     535           26 :    forces(:,iat)=vec2(:)
     536              :  end do
     537              : 
     538              : !Calculate the piezoelectric force-response tensor including the improper contribution
     539          782 :  piezofr(:,:,:,:) = SUM(phi1(1:3,1:natom,1:3,1:natom,1:3), DIM=4)
     540            8 :  do iatd=1,3
     541           80 :    piezofr(iatd,:,:,iatd) = piezofr(iatd,:,:,iatd) + TRANSPOSE(forces(:,:))
     542              :  end do
     543              : 
     544              : !Calculate the ion-relaxed internal strain tensor
     545              :  !First we need to obtain the pseudo-inverse of the dynamical matrix
     546            2 :  call dm_psinv(asr,blkval2d,d2asr,ab_out,psinvdm,mpert,natom)
     547              : 
     548              :  !Perfom the product with the piezo force-response
     549          242 :  intstrn(:,:,:,:)=zero
     550            8 :  do qvecd=1,3
     551           26 :    do katd=1,3
     552           78 :      do iatd=1,3
     553          234 :        do iat=1,natom
     554          162 :          ivar=(iat-1)*3+iatd
     555          702 :          do jatd=1,3
     556         2268 :            do jat=1,natom
     557         1620 :              jvar=(jat-1)*3+jatd
     558              : 
     559              :              intstrn(qvecd,katd,iatd,iat)= intstrn(qvecd,katd,iatd,iat) + &
     560         2106 :            psinvdm(ivar,jvar)*piezofr(jatd,jat,katd,qvecd)
     561              : 
     562              :            end do
     563              :          end do
     564              :        end do
     565              :      end do
     566              :    end do
     567              :  end do
     568              : 
     569            2 :  if (.not.intstrn_only) then
     570              :  !Finally calculate the mixed contribution to the FxE tensor
     571            2 :    mixflexo(:,:,:,:)=zero
     572            8 :    do elfd=1,3
     573           26 :      do qvecd=1,3
     574           78 :        do katd=1,3
     575          234 :          do qvecd2=1,3
     576          702 :            do iatd=1,3
     577         2106 :              do iat=1,natom
     578              : 
     579              :                mixflexo(elfd,qvecd,katd,qvecd2)=mixflexo(elfd,qvecd,katd,qvecd2) - &
     580         1944 :              pol1(elfd,qvecd,iatd,iat)*intstrn(qvecd2,katd,iatd,iat)*confac
     581              : 
     582              :             end do
     583              :           end do
     584              :         end do
     585              :       end do
     586              :     end do
     587              :   end do
     588              :  end if
     589              : 
     590              : !Print results
     591            2 :  iwrite = ab_out > 0
     592            2 :  if (iwrite) then
     593            2 :    write(msg,'(3a)')ch10,' Force-response internal strain tensor from long-wave magnitudes (units: Hartree/Bohr)',ch10
     594            6 :    call wrtout([ab_out,std_out],msg,'COLL')
     595            2 :    write(msg,*)' atom   dir        xx          yy          zz          yz          xz          xy'
     596            6 :    call wrtout([ab_out,std_out],msg,'COLL')
     597            8 :    do iat=1,natom
     598            6 :      write(msg,'(2x,i3,3x,a3,2x,6f12.6)') iat, 'x', piezofr(1,iat,1,1),piezofr(1,iat,2,2),piezofr(1,iat,3,3),&
     599           12 :                                                     piezofr(1,iat,2,3),piezofr(1,iat,1,3),piezofr(1,iat,1,2)
     600           18 :      call wrtout([ab_out,std_out],msg,'COLL')
     601            6 :      write(msg,'(2x,i3,3x,a3,2x,6f12.6)') iat, 'y', piezofr(2,iat,1,1),piezofr(2,iat,2,2),piezofr(2,iat,3,3),&
     602           12 :                                                     piezofr(2,iat,2,3),piezofr(2,iat,1,3),piezofr(2,iat,1,2)
     603           18 :      call wrtout([ab_out,std_out],msg,'COLL')
     604            6 :      write(msg,'(2x,i3,3x,a3,2x,6f12.6)') iat, 'z', piezofr(3,iat,1,1),piezofr(3,iat,2,2),piezofr(3,iat,3,3),&
     605           12 :                                                     piezofr(3,iat,2,3),piezofr(3,iat,1,3),piezofr(3,iat,1,2)
     606           20 :      call wrtout([ab_out,std_out],msg,'COLL')
     607              :    end do
     608              : 
     609            2 :    write(msg,'(3a)')ch10,' Displacement-response internal strain tensor from long-wave magnitudes (units: Bohr)',ch10
     610            6 :    call wrtout([ab_out,std_out],msg,'COLL')
     611            2 :    write(msg,*)' atom   dir        xx          yy          zz          yz          xz          xy'
     612            6 :    call wrtout([ab_out,std_out],msg,'COLL')
     613            8 :    do iat=1,natom
     614            6 :      write(msg,'(2x,i3,3x,a3,2x,6f12.6)') iat, 'x', intstrn(1,1,1,iat),intstrn(2,2,1,iat),intstrn(3,3,1,iat),&
     615           12 :                                                          intstrn(2,3,1,iat),intstrn(1,3,1,iat),intstrn(1,2,1,iat)
     616           18 :      call wrtout([ab_out,std_out],msg,'COLL')
     617            6 :      write(msg,'(2x,i3,3x,a3,2x,6f12.6)') iat, 'y', intstrn(1,1,2,iat),intstrn(2,2,2,iat),intstrn(3,3,2,iat),&
     618           12 :                                                          intstrn(2,3,2,iat),intstrn(1,3,2,iat),intstrn(1,2,2,iat)
     619           18 :      call wrtout([ab_out,std_out],msg,'COLL')
     620            6 :      write(msg,'(2x,i3,3x,a3,2x,6f12.6)') iat, 'z', intstrn(1,1,3,iat),intstrn(2,2,3,iat),intstrn(3,3,3,iat),&
     621           12 :                                                          intstrn(2,3,3,iat),intstrn(1,3,3,iat),intstrn(1,2,3,iat)
     622           20 :      call wrtout([ab_out,std_out],msg,'COLL')
     623              :    end do
     624              : 
     625            2 :    if (.not.intstrn_only) then
     626            2 :      write(msg,'(3a)')ch10,' Type-II mixed contribution to flexoelectric tensor (units: nC/m)',ch10
     627            6 :      call wrtout([ab_out,std_out],msg,'COLL')
     628            2 :      write(msg,*)'           xx          yy          zz          yz          xz          xy'
     629            6 :      call wrtout([ab_out,std_out],msg,'COLL')
     630           14 :      do ivar=1,6
     631           12 :        elfd=alpha(ivar)
     632           12 :        qvecd=beta(ivar)
     633           12 :        write(msg,'(3x,a2,6f12.6)') voigt(ivar),mixflexo(elfd,qvecd,1,1),mixflexo(elfd,qvecd,2,2),mixflexo(elfd,qvecd,3,3),&
     634           24 :                              mixflexo(elfd,qvecd,2,3),mixflexo(elfd,qvecd,1,3),mixflexo(elfd,qvecd,1,2)
     635           38 :        call wrtout([ab_out,std_out],msg,'COLL')
     636              :      end do
     637            8 :      do ivar=4,6
     638            6 :        elfd=beta(ivar)
     639            6 :        qvecd=alpha(ivar)
     640            6 :        write(msg,'(3x,a2,6f12.6)') voigt(ivar+3),mixflexo(elfd,qvecd,1,1),mixflexo(elfd,qvecd,2,2),mixflexo(elfd,qvecd,3,3),&
     641           12 :                              mixflexo(elfd,qvecd,2,3),mixflexo(elfd,qvecd,1,3),mixflexo(elfd,qvecd,1,2)
     642           20 :        call wrtout([ab_out,std_out],msg,'COLL')
     643              :      end do
     644              :    end if
     645              :  end if
     646              : 
     647              :  DBG_EXIT("COLL")
     648              : 
     649            2 :  end subroutine dtmixflexo
     650              : !!***
     651              : 
     652              : !!****f* m_ddb/dtlattflexo
     653              : !! NAME
     654              : !! dtlattflexo
     655              : !!
     656              : !! FUNCTION
     657              : !! Reads Phi^(1), flexoelectric force response and internal strain tensors
     658              : !! in the Gamma Block coming from the Derivative Data Base
     659              : !! (long wave third-order derivatives). And computes the lattice mediated
     660              : !! contribution to the flexoelectric tensor.
     661              : !! It also computes and writes the Lagrangian Elastic tensor.
     662              : !!
     663              : !! INPUTS
     664              : !! amu(ntypat)=mass each atom type in the unit cell
     665              : !! blkval1d(2,3,mpert,3,mpert)= 1st derivative wrt stress (at least)
     666              : !! blkval2d(2,3,mpert,3,mpert)= 2nd derivatives wrt atom displacements and electric field (at least)
     667              : !! blkvalA(2,3*mpert*3*mpert*3*mpert)= matrix of third-order energies for FxE force response tensor
     668              : !! blkvalB(2,3*mpert*3*mpert*3*mpert)= matrix of third-order energies for Phi^(1) tensor
     669              : !! ddb_version = 8 digit integer giving date. To mantain compatibility with old DDB files.
     670              : !! intstrn(3,3,3,natom)= relaxed-ion internal strain tensor
     671              : !! mpert= maximum number of ipert
     672              : !! natom= number of atoms in unit cell
     673              : !! piezofr(3,natom,3,3)= piezoelectric force response tensor (required to compute the Lagrange elastic tensor)
     674              : !! prtvol= if >1 print all tensors entering the structure of lattflexo
     675              : !! psinvdm(3*natom,3*natom) = pseudo inverse of dynamical matrix
     676              : !! typat(natom)= Type of each atom in the unit cell
     677              : !! ucvol= unit cell volume
     678              : !!
     679              : !! OUTPUT
     680              : !! lattflexo(3,3,3,3) = type-II lattice contribution to the Flexoelectric Tensor
     681              : !!
     682              : !! SOURCE
     683              : 
     684            2 : subroutine dtlattflexo(amu,blkval1d,blkvalA,blkvalB,ddb_version,intstrn,lattflexo,mpert,natom,&
     685            2 :                      & ntypat,piezofr,prtvol,psinvdm,typat,ucvol,zeff)
     686              : 
     687              : !Arguments -------------------------------
     688              : !scalars
     689              :  integer,intent(in) :: ddb_version,mpert,natom,ntypat,prtvol
     690              :  real(dp),intent(in) :: ucvol
     691              : 
     692              : !arrays
     693              :  integer,intent(in) :: typat(natom)
     694              :  real(dp),intent(in) :: amu(ntypat)
     695              :  real(dp),intent(in) :: blkval1d(2,3,mpert,3,mpert)
     696              :  real(dp),intent(in) :: blkvalA(2,3*mpert*3*mpert*3*mpert)
     697              :  real(dp),intent(in) :: blkvalB(2,3*mpert*3*mpert*3*mpert)
     698              :  real(dp),intent(in) :: intstrn(3,3,3,natom)
     699              :  real(dp),intent(in) :: piezofr(3,natom,3,3)
     700              :  real(dp),intent(in) :: psinvdm(3*natom,3*natom)
     701              :  real(dp),intent(in) :: zeff(3,3,natom)
     702              :  real(dp),intent(out) :: lattflexo(3,3,3,3)
     703              : 
     704              : !Local variables -------------------------
     705              : !scalars
     706              :  integer,parameter :: cvrsio8=20100401
     707              :  integer :: elfd,iat,iatd,istrs,ivar,jat,jatd,jvar,kat,katd,strsd
     708              :  integer :: strsd1,strsd2,strst,qvecd,qvecd2
     709              :  logical :: iwrite
     710              :  real(dp) :: fac,mtot
     711              :  real(dp),parameter :: confac=e_Cb/Bohr_meter*1.d9
     712              :  character(len=500) :: msg
     713              : !arrays
     714              :  integer,parameter :: alpha(6)=(/1,2,3,2,1,1/),beta(6)=(/1,2,3,3,3,2/)
     715              :  real(dp) :: frcelast_t2(3,3,3,3)
     716            4 :  real(dp) :: Csupkap(3,natom,3,3,3),Csupkapsum(3,3,3,3)
     717            4 :  real(dp) :: d3cart(2,3,mpert,3,mpert,3,mpert)
     718            4 :  real(dp) :: flexois(3,natom,3,3,3)
     719            4 :  real(dp) :: flexofr(3,natom,3,3,3)
     720            4 :  real(dp) :: hatCsupkap(3,natom,3,3,3)
     721              :  real(dp) :: lmcelast(3,3,3,3)
     722            4 :  real(dp) :: phi1(3,natom,3,natom,3)
     723              :  real(dp) :: ricelast_t2(3,3,3,3)
     724            4 :  real(dp) :: roundbkt_k(3,3,3,3,natom)
     725              :  real(dp) :: sqrbkt_t1(3,3,3,3)
     726              :  real(dp) :: stress(3,3)
     727              :  character(len=2) :: voigt(9)=(/'xx','yy','zz','yz','xz','xy','zy','zx','yx'/)
     728              : 
     729              : ! MR: Kept for testing
     730              : ! integer :: i,j,k,l
     731              : ! real(dp) :: delik,deljk,delil,deljl
     732              : 
     733              : ! *********************************************************************
     734              : 
     735              :  DBG_ENTER("COLL")
     736              : 
     737              : !Extraction of the stress tensor
     738            2 :  stress(1,1)=blkval1d(1,1,natom+3,1,1)
     739            2 :  stress(2,2)=blkval1d(1,2,natom+3,1,1)
     740            2 :  stress(3,3)=blkval1d(1,3,natom+3,1,1)
     741            2 :  stress(2,3)=blkval1d(1,1,natom+4,1,1);stress(3,2)=stress(2,3)
     742            2 :  stress(1,3)=blkval1d(1,2,natom+4,1,1);stress(3,1)=stress(1,3)
     743            2 :  stress(1,2)=blkval1d(1,3,natom+4,1,1);stress(2,1)=stress(1,2)
     744              : 
     745              : !Calculate the sublattice-dependent round bracket tensor of PRB 88,174106 (2013)
     746              : !First we need to extract the Phi^(1) tensor
     747       375606 :  d3cart(1,:,:,:,:,:,:) = reshape(blkvalB(1,:),shape = (/3,mpert,3,mpert,3,mpert/))
     748       375606 :  d3cart(2,:,:,:,:,:,:) = reshape(blkvalB(2,:),shape = (/3,mpert,3,mpert,3,mpert/))
     749              : 
     750              : !Define the factors to apply if DDB file has been created with the old version of
     751              : !the longwave driver.
     752            2 :  if (ddb_version <= cvrsio8) then
     753              :    fac=-two
     754              :  else
     755            1 :    fac=-one
     756              :  end if
     757              : 
     758              :  phi1(:,:,:,:,:) = fac*RESHAPE(d3cart(2,1:3,1:natom,1:3,1:natom,1:3,natom+8), &
     759          812 :                                & SHAPE=[3,natom,3,natom,3])
     760              : 
     761              : !Now perform the multiplication with the internal strain
     762          728 :  roundbkt_k(:,:,:,:,:)=zero
     763            8 :  do iat=1,natom
     764           26 :    do iatd=1,3
     765           78 :      do qvecd2=1,3
     766          234 :        do jatd=1,3
     767          702 :          do qvecd=1,3
     768         2106 :            do katd=1,3
     769         6804 :              do kat=1,natom
     770              :                roundbkt_k(iatd,qvecd,jatd,qvecd2,iat)=roundbkt_k(iatd,qvecd,jatd,qvecd2,iat) &
     771         6318 :              + phi1(iatd,iat,katd,kat,qvecd)*intstrn(qvecd2,jatd,katd,kat)
     772              :              end do
     773              :            end do
     774              : !         write(100,'(5i3,1x,f12.6)') iat, iatd,qvecd,jatd,qvecd2,roundbkt_k(iatd,qvecd,jatd,qvecd2,iat)
     775              :          end do
     776              :        end do
     777              :      end do
     778              :    end do
     779              :  end do
     780              : 
     781              : !Calculate now the Lagrange elastic tensors
     782              : !First we need to extract the clamped-ion flexoelectric force response tensor
     783       375606 :  d3cart(1,:,:,:,:,:,:) = reshape(blkvalA(1,:),shape = (/3,mpert,3,mpert,3,mpert/))
     784       375606 :  d3cart(2,:,:,:,:,:,:) = reshape(blkvalA(2,:),shape = (/3,mpert,3,mpert,3,mpert/))
     785              : 
     786              : !Define the factors to apply if DDB file has been created with the old version of
     787              : !the longwave driver.
     788            2 :  if (ddb_version <= cvrsio8) then
     789              :    fac=-two
     790              :  else
     791            1 :    fac=one
     792              :  end if
     793              : 
     794           14 :  do istrs=1,6
     795           12 :    strsd1=alpha(istrs)
     796           12 :    strsd2=beta(istrs)
     797           12 :    strst=natom+3; if (istrs>3) strst=natom+4
     798            6 :    strsd=istrs; if (istrs>3) strsd=istrs-3
     799           50 :    do qvecd=1,3
     800          156 :      do iat=1,natom
     801          468 :        do iatd=1,3
     802          324 :          flexofr(iatd,iat,qvecd,strsd1,strsd2)=fac*d3cart(1,iatd,iat,strsd,strst,qvecd,natom+8)
     803          432 :          if (istrs>3) flexofr(iatd,iat,qvecd,strsd2,strsd1)=flexofr(iatd,iat,qvecd,strsd1,strsd2)
     804              :        end do
     805              :      end do
     806              :    end do
     807              :  end do
     808              : 
     809              : !Now compute the type-II frozen-ion elastic tensor (without stress corrected)
     810            2 :  fac=one/ucvol
     811          728 :  frcelast_t2(:,:,:,:) = fac*SUM(flexofr(1:3,1:natom,1:3,1:3,1:3), DIM=2)
     812              : 
     813              : !Now convert to type-I to obtain the square bracketed tensor of Born and Huang
     814            8 :  do qvecd=1,3
     815           26 :    do strsd2=1,3
     816           78 :      do strsd1=1,3
     817              :        sqrbkt_t1(1:3,strsd1,strsd2,qvecd)=half*(frcelast_t2(1:3,qvecd,strsd1,strsd2) + &
     818          234 :        & frcelast_t2(1:3,strsd2,strsd1,qvecd))
     819              :      end do
     820              :    end do
     821              :  end do
     822              : 
     823              : !Now correct the stress in the square bracketed tesnor tensor
     824            8 :  do qvecd=1,3
     825           26 :    do strsd2=1,3
     826           78 :      do strsd1=1,3
     827          234 :        do iatd=1,3
     828          216 :          if (iatd==strsd1) then
     829           54 :            sqrbkt_t1(iatd,strsd1,strsd2,qvecd)=sqrbkt_t1(iatd,strsd1,strsd2,qvecd) - stress(strsd2,qvecd)
     830              :          endif
     831              :        end do
     832              :      end do
     833              :    end do
     834              :  end do
     835              : 
     836              : !Now convert back to type-II in order to obtain the frozen ion Lagrange elastic tensor.
     837            2 :  frcelast_t2(:,:,:,:)=zero
     838            8 :  do iatd=1,3
     839           26 :    do qvecd=1,3
     840           78 :      do strsd1=1,3
     841          234 :        do strsd2=1,3
     842              :          frcelast_t2(iatd,qvecd,strsd1,strsd2)=sqrbkt_t1(iatd,strsd1,qvecd,strsd2) + &
     843          216 :        & sqrbkt_t1(iatd,strsd2,strsd1,qvecd)-sqrbkt_t1(iatd,qvecd,strsd2,strsd1)
     844              :        end do
     845              :      end do
     846              :    end do
     847              :  end do
     848              : 
     849              : !MR: kept for testing only. If uncommented the resulting elastic tensors must agree with HWRV's ones
     850              : ! write(ab_out,*)
     851              : ! write(ab_out,*) "Stress tensor"
     852              : ! do i=1,3
     853              : !   write(ab_out,*) stress(i,:)
     854              : ! end do
     855              : ! do i=1,3
     856              : !   do j=1,3
     857              : !     do k=1,3
     858              : !       delik=0.d0; if(i==k) delik=1.d0
     859              : !       deljk=0.d0; if(j==k) deljk=1.d0
     860              : !       do l=1,3
     861              : !         delil=0.d0; if(i==l) delil=1.d0
     862              : !         deljl=0.d0; if(j==l) deljl=1.d0
     863              : 
     864              : !         frcelast_t2(i,j,k,l)=frcelast_t2(i,j,k,l) + &
     865              : !       & 0.5d0*( deljk*stress(i,l) + delik*stress(j,l) + delil*stress(j,k) &
     866              : !       & + deljl*stress(i,k) )
     867              : 
     868              : !       end do
     869              : !     end do
     870              : !   end do
     871              : ! end do
     872              : 
     873              : !Now compute the contribution to the elastic tensor due to ion relaxations
     874              : !and sum with the clamped ion elastic tensor to obtain the relaxed ion one
     875            2 :  lmcelast(:,:,:,:)=zero
     876            8 :  do strsd2=1,3
     877           26 :    do strsd1=1,3
     878           78 :      do qvecd=1,3
     879          234 :        do jatd=1,3
     880          702 :          do iatd=1,3
     881         2106 :            do iat=1,natom
     882              :              lmcelast(jatd,qvecd,strsd1,strsd2)=lmcelast(jatd,qvecd,strsd1,strsd2) - &
     883         1944 :              intstrn(jatd,qvecd,iatd,iat)*piezofr(iatd,iat,strsd1,strsd2)*fac
     884              :            end do
     885              :          end do
     886              :        end do
     887              :      end do
     888              :    end do
     889              :  end do
     890          242 :  ricelast_t2(:,:,:,:) = frcelast_t2(:,:,:,:) + lmcelast(:,:,:,:)
     891              : 
     892              : !In last place compute the lattice contribution to the FxE tensor
     893              : !First obtain the C^{\kappa} tensor of Eq. 59 of PRB 88,174106 (2013)
     894              : !and its sublattice summation
     895            2 :  Csupkapsum(:,:,:,:)=zero
     896            8 :  do strsd2=1,3
     897           26 :    do strsd1=1,3
     898           78 :      do qvecd=1,3
     899          234 :        do iatd=1,3
     900          702 :          do iat=1,natom
     901              :            Csupkap(iatd,iat,qvecd,strsd1,strsd2)=flexofr(iatd,iat,qvecd,strsd1,strsd2) + &
     902          486 :          & roundbkt_k(iatd,qvecd,strsd1,strsd2,iat)
     903              :            Csupkapsum(iatd,qvecd,strsd1,strsd2)=Csupkapsum(iatd,qvecd,strsd1,strsd2) + &
     904          648 :          & Csupkap(iatd,iat,qvecd,strsd1,strsd2)
     905              :          end do
     906              :        end do
     907              :      end do
     908              :    end do
     909              :  end do
     910              : 
     911              : !Then separate the mass-dependent part
     912            2 :  mtot=zero
     913            8 :  do iat=1,natom
     914            8 :    mtot=mtot + amu(typat(iat))
     915              :  end do
     916              : 
     917            8 :  do strsd2=1,3
     918           26 :    do strsd1=1,3
     919           78 :      do qvecd=1,3
     920          234 :        do iatd=1,3
     921          702 :          do iat=1,natom
     922              :            hatCsupkap(iatd,iat,qvecd,strsd1,strsd2)=Csupkap(iatd,iat,qvecd,strsd1,strsd2) - &
     923          648 :          & amu(typat(iat))/mtot*Csupkapsum(iatd,qvecd,strsd1,strsd2)
     924              :          end do
     925              :        end do
     926              :      end do
     927              :    end do
     928              :  end do
     929              : 
     930              : !Now compute the type-II flexoelectric internal strain tensor
     931          728 :  flexois(:,:,:,:,:)=zero
     932            8 :  do strsd2=1,3
     933           26 :    do strsd1=1,3
     934           78 :      do qvecd=1,3
     935          234 :        do iat=1,natom
     936          702 :          do iatd=1,3
     937          486 :            ivar=(iat-1)*3+iatd
     938         2268 :            do jat=1,natom
     939         6966 :              do jatd=1,3
     940         4860 :                jvar=(jat-1)*3+jatd
     941              :                flexois(iatd,iat,qvecd,strsd1,strsd2)=flexois(iatd,iat,qvecd,strsd1,strsd2) + &
     942         6480 :              & psinvdm(ivar,jvar)*hatCsupkap(jatd,jat,qvecd,strsd1,strsd2)
     943              :              end do
     944              :            end do
     945              :          end do
     946              :        end do
     947              :      end do
     948              :    end do
     949              :  end do
     950              : 
     951              : !Finally multiply by the effective charges to obtain the FxE tensor
     952            2 :  lattflexo(:,:,:,:)=zero
     953            8 :  do strsd2=1,3
     954           26 :    do strsd1=1,3
     955           78 :      do qvecd=1,3
     956          234 :        do elfd=1,3
     957          702 :          do iat=1,natom
     958         2106 :            do iatd=1,3
     959              :              lattflexo(elfd,qvecd,strsd1,strsd2)=lattflexo(elfd,qvecd,strsd1,strsd2) + &
     960         1944 :            & zeff(elfd,iatd,iat)*flexois(iatd,iat,qvecd,strsd1,strsd2)/ucvol*confac
     961              :            end do
     962              :          end do
     963              :        end do
     964              :      end do
     965              :    end do
     966              :  end do
     967              : 
     968              : 
     969            2 :  iwrite = ab_out > 0
     970            2 :  if (iwrite) then
     971            2 :    write(msg,'(3a)')ch10,' Lagrange elastic tensor from long wave magnitudes (clamped ion) (units= 10^2 GPa) ',ch10
     972            6 :    call wrtout([ab_out,std_out],msg,'COLL')
     973            2 :    write(msg,*)'      xx          yy          zz          yz          xz          xy'
     974            6 :    call wrtout([ab_out,std_out],msg,'COLL')
     975          242 :    frcelast_t2(:,:,:,:)=frcelast_t2(:,:,:,:)*HaBohr3_GPa/100.00_dp
     976           14 :    do ivar=1,6
     977           12 :      iatd=alpha(ivar)
     978           12 :      qvecd=beta(ivar)
     979           12 :      write(msg,'(9f12.6)') frcelast_t2(iatd,qvecd,1,1), frcelast_t2(iatd,qvecd,2,2),frcelast_t2(iatd,qvecd,3,3), &
     980           24 :                            frcelast_t2(iatd,qvecd,2,3), frcelast_t2(iatd,qvecd,1,3),frcelast_t2(iatd,qvecd,1,2)
     981              : 
     982           38 :      call wrtout([ab_out,std_out],msg,'COLL')
     983              :    end do
     984              : 
     985            2 :    write(msg,'(3a)')ch10,' Lagrange elastic tensor from long wave magnitudes (relaxed ion) (units= 10^2 GPa) ',ch10
     986            6 :    call wrtout([ab_out,std_out],msg,'COLL')
     987            2 :    write(msg,*)'      xx          yy          zz          yz          xz          xy'
     988            6 :    call wrtout([ab_out,std_out],msg,'COLL')
     989          242 :    ricelast_t2(:,:,:,:)=ricelast_t2(:,:,:,:)*HaBohr3_GPa/100.00_dp
     990           14 :    do ivar=1,6
     991           12 :      iatd=alpha(ivar)
     992           12 :      qvecd=beta(ivar)
     993           12 :      write(msg,'(9f12.6)') ricelast_t2(iatd,qvecd,1,1), ricelast_t2(iatd,qvecd,2,2),ricelast_t2(iatd,qvecd,3,3), &
     994           24 :                            ricelast_t2(iatd,qvecd,2,3), ricelast_t2(iatd,qvecd,1,3),ricelast_t2(iatd,qvecd,1,2)
     995              : 
     996           38 :      call wrtout([ab_out,std_out],msg,'COLL')
     997              :    end do
     998            2 :    if (prtvol > 1) then
     999            0 :      write(msg,'(3a)')ch10,' (...)^kappa contribution to the flexoelectric force-response tensor (units: eV)',ch10
    1000            0 :      call wrtout([ab_out,std_out],msg,'COLL')
    1001            0 :      write(msg,*)' atom   dir        xx           yy           zz           yz           xz           xy'
    1002            0 :      call wrtout([ab_out,std_out],msg,'COLL')
    1003            0 :      roundbkt_k(:,:,:,:,:)=roundbkt_k(:,:,:,:,:)*Ha_eV
    1004            0 :      do iat=1,natom
    1005            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'xx', roundbkt_k(1,1,1,1,iat), roundbkt_k(1,1,2,2,iat), &
    1006            0 :                & roundbkt_k(1,1,3,3,iat),roundbkt_k(1,1,2,3,iat),roundbkt_k(1,1,1,3,iat),roundbkt_k(1,1,1,2,iat)
    1007            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1008            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'yy', roundbkt_k(2,2,1,1,iat), roundbkt_k(2,2,2,2,iat), &
    1009            0 :                & roundbkt_k(2,2,3,3,iat),roundbkt_k(2,2,2,3,iat),roundbkt_k(2,2,1,3,iat),roundbkt_k(2,2,1,2,iat)
    1010            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1011            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'zz', roundbkt_k(3,3,1,1,iat), roundbkt_k(3,3,2,2,iat), &
    1012            0 :                & roundbkt_k(3,3,3,3,iat),roundbkt_k(3,3,2,3,iat),roundbkt_k(3,3,1,3,iat),roundbkt_k(3,3,1,2,iat)
    1013            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1014            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'yz', roundbkt_k(2,3,1,1,iat), roundbkt_k(2,3,2,2,iat), &
    1015            0 :                & roundbkt_k(2,3,3,3,iat),roundbkt_k(2,3,2,3,iat),roundbkt_k(2,3,1,3,iat),roundbkt_k(2,3,1,2,iat)
    1016            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1017            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'xz', roundbkt_k(1,3,1,1,iat), roundbkt_k(1,3,2,2,iat), &
    1018            0 :                & roundbkt_k(1,3,3,3,iat),roundbkt_k(1,3,2,3,iat),roundbkt_k(1,3,1,3,iat),roundbkt_k(1,3,1,2,iat)
    1019            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1020            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'xy', roundbkt_k(1,2,1,1,iat), roundbkt_k(1,2,2,2,iat), &
    1021            0 :                & roundbkt_k(1,2,3,3,iat),roundbkt_k(1,2,2,3,iat),roundbkt_k(1,2,1,3,iat),roundbkt_k(1,2,1,2,iat)
    1022            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1023            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'zy', roundbkt_k(3,2,1,1,iat), roundbkt_k(3,2,2,2,iat), &
    1024            0 :                & roundbkt_k(3,2,3,3,iat),roundbkt_k(3,2,2,3,iat),roundbkt_k(3,2,1,3,iat),roundbkt_k(3,2,1,2,iat)
    1025            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1026            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'zx', roundbkt_k(3,1,1,1,iat), roundbkt_k(3,1,2,2,iat), &
    1027            0 :                & roundbkt_k(3,1,3,3,iat),roundbkt_k(3,1,2,3,iat),roundbkt_k(3,1,1,3,iat),roundbkt_k(3,1,1,2,iat)
    1028            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1029            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'yx', roundbkt_k(2,1,1,1,iat), roundbkt_k(2,1,2,2,iat), &
    1030            0 :                & roundbkt_k(2,1,3,3,iat),roundbkt_k(2,1,2,3,iat),roundbkt_k(2,1,1,3,iat),roundbkt_k(2,1,1,2,iat)
    1031            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1032              :      end do
    1033              : 
    1034            0 :      write(msg,'(3a)')ch10,' [...]^kappa contribution to the flexoelectric force-response tensor (units: eV)',ch10
    1035            0 :      call wrtout([ab_out,std_out],msg,'COLL')
    1036            0 :      write(msg,*)' atom   dir        xx           yy           zz           yz           xz           xy'
    1037            0 :      call wrtout([ab_out,std_out],msg,'COLL')
    1038            0 :      flexofr(:,:,:,:,:)=flexofr(:,:,:,:,:)*Ha_eV
    1039            0 :      do iat=1,natom
    1040            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'xx', flexofr(1,iat,1,1,1),flexofr(1,iat,1,2,2),flexofr(1,iat,1,3,3),&
    1041            0 :                                                      & flexofr(1,iat,1,2,3),flexofr(1,iat,1,1,3),flexofr(1,iat,1,1,2)
    1042            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1043            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'yy', flexofr(2,iat,2,1,1),flexofr(2,iat,2,2,2),flexofr(2,iat,2,3,3),&
    1044            0 :                                                      & flexofr(2,iat,2,2,3),flexofr(2,iat,2,1,3),flexofr(2,iat,2,1,2)
    1045            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1046            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'zz', flexofr(3,iat,3,1,1),flexofr(3,iat,3,2,2),flexofr(3,iat,3,3,3),&
    1047            0 :                                                      & flexofr(3,iat,3,2,3),flexofr(3,iat,3,1,3),flexofr(3,iat,3,1,2)
    1048            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1049            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'yz', flexofr(2,iat,3,1,1),flexofr(2,iat,3,2,2),flexofr(2,iat,3,3,3),&
    1050            0 :                                                      & flexofr(2,iat,3,2,3),flexofr(2,iat,3,1,3),flexofr(2,iat,3,1,2)
    1051            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1052            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'xz', flexofr(1,iat,3,1,1),flexofr(1,iat,3,2,2),flexofr(1,iat,3,3,3),&
    1053            0 :                                                      & flexofr(1,iat,3,2,3),flexofr(1,iat,3,1,3),flexofr(1,iat,3,1,2)
    1054            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1055            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'xy', flexofr(1,iat,2,1,1),flexofr(1,iat,2,2,2),flexofr(1,iat,2,3,3),&
    1056            0 :                                                      & flexofr(1,iat,2,2,3),flexofr(1,iat,2,1,3),flexofr(1,iat,2,1,2)
    1057            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1058            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'zy', flexofr(3,iat,2,1,1),flexofr(3,iat,2,2,2),flexofr(3,iat,2,3,3),&
    1059            0 :                                                      & flexofr(3,iat,2,2,3),flexofr(3,iat,2,1,3),flexofr(3,iat,2,1,2)
    1060            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1061            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'zx', flexofr(3,iat,1,1,1),flexofr(3,iat,1,2,2),flexofr(3,iat,1,3,3),&
    1062            0 :                                                      & flexofr(3,iat,1,2,3),flexofr(3,iat,1,1,3),flexofr(3,iat,1,1,2)
    1063            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1064            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'yx', flexofr(2,iat,1,1,1),flexofr(2,iat,1,2,2),flexofr(2,iat,1,3,3),&
    1065            0 :                                                      & flexofr(2,iat,1,2,3),flexofr(2,iat,1,1,3),flexofr(2,iat,1,1,2)
    1066            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1067              :        end do
    1068              :    end if
    1069              : 
    1070            2 :    write(msg,'(3a)')ch10,' Flexoelectric force-response tensor (units: eV)',ch10
    1071            6 :    call wrtout([ab_out,std_out],msg,'COLL')
    1072            2 :    write(msg,*)' atom   dir        xx           yy           zz           yz           xz           xy'
    1073            6 :    call wrtout([ab_out,std_out],msg,'COLL')
    1074          728 :    Csupkap(:,:,:,:,:)=Csupkap(:,:,:,:,:)*Ha_eV
    1075            8 :    do iat=1,natom
    1076            6 :      write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'xx', Csupkap(1,iat,1,1,1),Csupkap(1,iat,1,2,2),Csupkap(1,iat,1,3,3),&
    1077           12 :                                                    & Csupkap(1,iat,1,2,3),Csupkap(1,iat,1,1,3),Csupkap(1,iat,1,1,2)
    1078           18 :      call wrtout([ab_out,std_out],msg,'COLL')
    1079            6 :      write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'yy', Csupkap(2,iat,2,1,1),Csupkap(2,iat,2,2,2),Csupkap(2,iat,2,3,3),&
    1080           12 :                                                    & Csupkap(2,iat,2,2,3),Csupkap(2,iat,2,1,3),Csupkap(2,iat,2,1,2)
    1081           18 :      call wrtout([ab_out,std_out],msg,'COLL')
    1082            6 :      write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'zz', Csupkap(3,iat,3,1,1),Csupkap(3,iat,3,2,2),Csupkap(3,iat,3,3,3),&
    1083           12 :                                                    & Csupkap(3,iat,3,2,3),Csupkap(3,iat,3,1,3),Csupkap(3,iat,3,1,2)
    1084           18 :      call wrtout([ab_out,std_out],msg,'COLL')
    1085            6 :      write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'yz', Csupkap(2,iat,3,1,1),Csupkap(2,iat,3,2,2),Csupkap(2,iat,3,3,3),&
    1086           12 :                                                    & Csupkap(2,iat,3,2,3),Csupkap(2,iat,3,1,3),Csupkap(2,iat,3,1,2)
    1087           18 :      call wrtout([ab_out,std_out],msg,'COLL')
    1088            6 :      write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'xz', Csupkap(1,iat,3,1,1),Csupkap(1,iat,3,2,2),Csupkap(1,iat,3,3,3),&
    1089           12 :                                                    & Csupkap(1,iat,3,2,3),Csupkap(1,iat,3,1,3),Csupkap(1,iat,3,1,2)
    1090           18 :      call wrtout([ab_out,std_out],msg,'COLL')
    1091            6 :      write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'xy', Csupkap(1,iat,2,1,1),Csupkap(1,iat,2,2,2),Csupkap(1,iat,2,3,3),&
    1092           12 :                                                    & Csupkap(1,iat,2,2,3),Csupkap(1,iat,2,1,3),Csupkap(1,iat,2,1,2)
    1093           18 :      call wrtout([ab_out,std_out],msg,'COLL')
    1094            6 :      write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'zy', Csupkap(3,iat,2,1,1),Csupkap(3,iat,2,2,2),Csupkap(3,iat,2,3,3),&
    1095           12 :                                                    & Csupkap(3,iat,2,2,3),Csupkap(3,iat,2,1,3),Csupkap(3,iat,2,1,2)
    1096           18 :      call wrtout([ab_out,std_out],msg,'COLL')
    1097            6 :      write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'zx', Csupkap(3,iat,1,1,1),Csupkap(3,iat,1,2,2),Csupkap(3,iat,1,3,3),&
    1098           12 :                                                    & Csupkap(3,iat,1,2,3),Csupkap(3,iat,1,1,3),Csupkap(3,iat,1,1,2)
    1099           18 :      call wrtout([ab_out,std_out],msg,'COLL')
    1100            6 :      write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'yx', Csupkap(2,iat,1,1,1),Csupkap(2,iat,1,2,2),Csupkap(2,iat,1,3,3),&
    1101           12 :                                                    & Csupkap(2,iat,1,2,3),Csupkap(2,iat,1,1,3),Csupkap(2,iat,1,1,2)
    1102           20 :      call wrtout([ab_out,std_out],msg,'COLL')
    1103              :    end do
    1104            2 :    if (prtvol > 1) then
    1105            0 :      write(msg,'(3a)')ch10,' Flexoelectric force-response tensor minus mass dependent part (units: eV)',ch10
    1106            0 :      call wrtout([ab_out,std_out],msg,'COLL')
    1107            0 :      write(msg,*)' atom   dir        xx           yy           zz           yz           xz           xy'
    1108            0 :      call wrtout([ab_out,std_out],msg,'COLL')
    1109            0 :      hatCsupkap(:,:,:,:,:)=hatCsupkap(:,:,:,:,:)*Ha_eV
    1110            0 :      do iat=1,natom
    1111            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat,'xx',hatCsupkap(1,iat,1,1,1),hatCsupkap(1,iat,1,2,2),hatCsupkap(1,iat,1,3,3),&
    1112            0 :                                                      & hatCsupkap(1,iat,1,2,3),hatCsupkap(1,iat,1,1,3),hatCsupkap(1,iat,1,1,2)
    1113            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1114            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat,'yy',hatCsupkap(2,iat,2,1,1),hatCsupkap(2,iat,2,2,2),hatCsupkap(2,iat,2,3,3),&
    1115            0 :                                                      & hatCsupkap(2,iat,2,2,3),hatCsupkap(2,iat,2,1,3),hatCsupkap(2,iat,2,1,2)
    1116            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1117            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat,'zz',hatCsupkap(3,iat,3,1,1),hatCsupkap(3,iat,3,2,2),hatCsupkap(3,iat,3,3,3),&
    1118            0 :                                                      & hatCsupkap(3,iat,3,2,3),hatCsupkap(3,iat,3,1,3),hatCsupkap(3,iat,3,1,2)
    1119            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1120            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat,'yz',hatCsupkap(2,iat,3,1,1),hatCsupkap(2,iat,3,2,2),hatCsupkap(2,iat,3,3,3),&
    1121            0 :                                                      & hatCsupkap(2,iat,3,2,3),hatCsupkap(2,iat,3,1,3),hatCsupkap(2,iat,3,1,2)
    1122            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1123            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat,'xz',hatCsupkap(1,iat,3,1,1),hatCsupkap(1,iat,3,2,2),hatCsupkap(1,iat,3,3,3),&
    1124            0 :                                                      & hatCsupkap(1,iat,3,2,3),hatCsupkap(1,iat,3,1,3),hatCsupkap(1,iat,3,1,2)
    1125            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1126            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat,'xy',hatCsupkap(1,iat,2,1,1),hatCsupkap(1,iat,2,2,2),hatCsupkap(1,iat,2,3,3),&
    1127            0 :                                                      & hatCsupkap(1,iat,2,2,3),hatCsupkap(1,iat,2,1,3),hatCsupkap(1,iat,2,1,2)
    1128            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1129            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat,'zy',hatCsupkap(3,iat,2,1,1),hatCsupkap(3,iat,2,2,2),hatCsupkap(3,iat,2,3,3),&
    1130            0 :                                                      & hatCsupkap(3,iat,2,2,3),hatCsupkap(3,iat,2,1,3),hatCsupkap(3,iat,2,1,2)
    1131            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1132            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat,'zx',hatCsupkap(3,iat,1,1,1),hatCsupkap(3,iat,1,2,2),hatCsupkap(3,iat,1,3,3),&
    1133            0 :                                                      & hatCsupkap(3,iat,1,2,3),hatCsupkap(3,iat,1,1,3),hatCsupkap(3,iat,1,1,2)
    1134            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1135            0 :        write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat,'yx',hatCsupkap(2,iat,1,1,1),hatCsupkap(2,iat,1,2,2),hatCsupkap(2,iat,1,3,3),&
    1136            0 :                                                      & hatCsupkap(2,iat,1,2,3),hatCsupkap(2,iat,1,1,3),hatCsupkap(2,iat,1,1,2)
    1137            0 :        call wrtout([ab_out,std_out],msg,'COLL')
    1138              :      end do
    1139              :    end if
    1140              : 
    1141            2 :    write(msg,'(3a)')ch10,' Displacement-response flexoelectric internal strain tensor (units: Bohr^2)',ch10
    1142            6 :    call wrtout([ab_out,std_out],msg,'COLL')
    1143            2 :    write(msg,*)' atom   dir        xx           yy           zz           yz           xz           xy'
    1144            6 :    call wrtout([ab_out,std_out],msg,'COLL')
    1145            8 :    do iat=1,natom
    1146            6 :      write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'xx', flexois(1,iat,1,1,1),flexois(1,iat,1,2,2),flexois(1,iat,1,3,3),&
    1147           12 :                                                    & flexois(1,iat,1,2,3),flexois(1,iat,1,1,3),flexois(1,iat,1,1,2)
    1148           18 :      call wrtout([ab_out,std_out],msg,'COLL')
    1149            6 :      write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'yy', flexois(2,iat,2,1,1),flexois(2,iat,2,2,2),flexois(2,iat,2,3,3),&
    1150           12 :                                                    & flexois(2,iat,2,2,3),flexois(2,iat,2,1,3),flexois(2,iat,2,1,2)
    1151           18 :      call wrtout([ab_out,std_out],msg,'COLL')
    1152            6 :      write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'zz', flexois(3,iat,3,1,1),flexois(3,iat,3,2,2),flexois(3,iat,3,3,3),&
    1153           12 :                                                    & flexois(3,iat,3,2,3),flexois(3,iat,3,1,3),flexois(3,iat,3,1,2)
    1154           18 :      call wrtout([ab_out,std_out],msg,'COLL')
    1155            6 :      write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'yz', flexois(2,iat,3,1,1),flexois(2,iat,3,2,2),flexois(2,iat,3,3,3),&
    1156           12 :                                                    & flexois(2,iat,3,2,3),flexois(2,iat,3,1,3),flexois(2,iat,3,1,2)
    1157           18 :      call wrtout([ab_out,std_out],msg,'COLL')
    1158            6 :      write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'xz', flexois(1,iat,3,1,1),flexois(1,iat,3,2,2),flexois(1,iat,3,3,3),&
    1159           12 :                                                    & flexois(1,iat,3,2,3),flexois(1,iat,3,1,3),flexois(1,iat,3,1,2)
    1160           18 :      call wrtout([ab_out,std_out],msg,'COLL')
    1161            6 :      write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'xy', flexois(1,iat,2,1,1),flexois(1,iat,2,2,2),flexois(1,iat,2,3,3),&
    1162           12 :                                                    & flexois(1,iat,2,2,3),flexois(1,iat,2,1,3),flexois(1,iat,2,1,2)
    1163           18 :      call wrtout([ab_out,std_out],msg,'COLL')
    1164            6 :      write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'zy', flexois(3,iat,2,1,1),flexois(3,iat,2,2,2),flexois(3,iat,2,3,3),&
    1165           12 :                                                    & flexois(3,iat,2,2,3),flexois(3,iat,2,1,3),flexois(3,iat,2,1,2)
    1166           18 :      call wrtout([ab_out,std_out],msg,'COLL')
    1167            6 :      write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'zx', flexois(3,iat,1,1,1),flexois(3,iat,1,2,2),flexois(3,iat,1,3,3),&
    1168           12 :                                                    & flexois(3,iat,1,2,3),flexois(3,iat,1,1,3),flexois(3,iat,1,1,2)
    1169           18 :      call wrtout([ab_out,std_out],msg,'COLL')
    1170            6 :      write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'yx', flexois(2,iat,1,1,1),flexois(2,iat,1,2,2),flexois(2,iat,1,3,3),&
    1171           12 :                                                    & flexois(2,iat,1,2,3),flexois(2,iat,1,1,3),flexois(2,iat,1,1,2)
    1172           20 :      call wrtout([ab_out,std_out],msg,'COLL')
    1173              :    end do
    1174              : 
    1175            2 :    write(msg,'(3a)')ch10,' Type-II lattice contribution to flexoelectric tensor (units= nC/m) ',ch10
    1176            6 :    call wrtout([ab_out,std_out],msg,'COLL')
    1177            2 :    write(msg,*)'           xx          yy          zz          yz          xz          xy'
    1178            6 :    call wrtout([ab_out,std_out],msg,'COLL')
    1179           14 :    do ivar=1,6
    1180           12 :      elfd=alpha(ivar)
    1181           12 :      qvecd=beta(ivar)
    1182           12 :      write(msg,'(3x,a2,6f12.6)') voigt(ivar),lattflexo(elfd,qvecd,1,1),lattflexo(elfd,qvecd,2,2),lattflexo(elfd,qvecd,3,3),&
    1183           24 :                            lattflexo(elfd,qvecd,2,3),lattflexo(elfd,qvecd,1,3),lattflexo(elfd,qvecd,1,2)
    1184           38 :      call wrtout([ab_out,std_out],msg,'COLL')
    1185              :    end do
    1186            8 :    do ivar=4,6
    1187            6 :      elfd=beta(ivar)
    1188            6 :      qvecd=alpha(ivar)
    1189            6 :      write(msg,'(3x,a2,6f12.6)') voigt(ivar+3),lattflexo(elfd,qvecd,1,1),lattflexo(elfd,qvecd,2,2),lattflexo(elfd,qvecd,3,3),&
    1190           12 :                            lattflexo(elfd,qvecd,2,3),lattflexo(elfd,qvecd,1,3),lattflexo(elfd,qvecd,1,2)
    1191           20 :      call wrtout([ab_out,std_out],msg,'COLL')
    1192              :    end do
    1193              : 
    1194              :  end if
    1195              :  DBG_EXIT("COLL")
    1196              : 
    1197            2 :  end subroutine dtlattflexo
    1198              : !!***
    1199              : 
    1200              : !!****f* m_ddb/dm_psinv
    1201              : !! NAME
    1202              : !! dm_psinv
    1203              : !!
    1204              : !! FUNCTION
    1205              : !! Computes the pseudoinverse of the dynamical matrix (PRB 72, 035105 (2005)).
    1206              : !! This piece of code is copied from m_ddb_internalstr.F90.
    1207              : !!
    1208              : !! INPUTS
    1209              : !! asr= if /=0 acustic sume rule is imposed on the dynamical matrix
    1210              : !! blkval(2,3,mpert,3,mpert)= 2nd derivatives wrt two atom displacements (at least)
    1211              : !! d2asr(2,3,natom,3,natom)=ASR-correction
    1212              : !! iout=out file number
    1213              : !! mpert=maximum number of ipert
    1214              : !! natom=number of atoms in unit cell
    1215              : !!
    1216              : !! OUTPUT
    1217              : !! kmatrix(3*natom,3*natom) = array with the pseudo-inverse of dynamical matrix
    1218              : !!
    1219              : !! SOURCE
    1220              : 
    1221            2 :  subroutine dm_psinv(asr,blkval,d2asr,iout,kmatrix,mpert,natom)
    1222              : 
    1223              : !Arguments -------------------------------
    1224              : !scalars
    1225              :  integer,intent(in) :: asr,iout,mpert,natom
    1226              : !arrays
    1227              :  real(dp),intent(in) :: blkval(2,3,mpert,3,mpert)
    1228              :  real(dp),intent(in) :: d2asr(2,3,natom,3,natom)
    1229              :  real(dp),intent(out) :: kmatrix(3*natom,3*natom)
    1230              : 
    1231              : !Local variables -------------------------
    1232              : !scalars
    1233              :  integer :: ii1,ivarA
    1234              :  integer :: ivarB
    1235              :  integer :: ier
    1236              :  character(len=500) :: message
    1237              : !arrays
    1238            4 :  real(dp) :: Amatr(3*natom-3,3*natom-3),Apmatr(3*natom,3*natom)
    1239            4 :  real(dp) :: Bmatr(2,((3*natom-3)*(3*natom-2))/2)
    1240            4 :  real(dp) :: Bpmatr(2,(3*natom*(3*natom+1))/2),Cmatr(3*natom-3,3*natom-3)
    1241            4 :  real(dp) :: Cpmatr(3*natom,3*natom),Nmatr(3*natom,3*natom)
    1242            4 :  real(dp) :: eigval(3*natom-3),eigvalp(3*natom),eigvec(2,3*natom-3,3*natom-3)
    1243            4 :  real(dp) :: eigvecp(2,3*natom,3*natom)
    1244            4 :  real(dp) :: zhpev1(2,2*3*natom-4)
    1245            4 :  real(dp) :: zhpev1p(2,2*3*natom-1),zhpev2(3*3*natom-5),zhpev2p(3*3*natom-2)
    1246            4 :  real(dp) :: d2cart(2,3*natom,3*natom)
    1247              : 
    1248              : ! *********************************************************************
    1249              : 
    1250              :  DBG_ENTER("COLL")
    1251              : 
    1252          204 :  d2cart(1,:,:) = RESHAPE(blkval(1,1:3,1:natom,1:3,1:natom), SHAPE=[3*natom,3*natom])
    1253          200 :  d2cart(2,:,:) = zero
    1254              : 
    1255              : !Eventually impose the acoustic sum rule
    1256              : !FIXME: this might depend on ifcflag: impose that it is 0 or generalize
    1257            2 :  call asria_corr(asr,d2asr,d2cart,natom,natom)
    1258              :  !call asrq0_apply(asrq0, natom, mpert, msize, crystal%xcart, d2cart)
    1259          200 :  kmatrix(:,:) = d2cart(1,:,:)
    1260              : 
    1261              : !DEBUG
    1262              : !write(std_out,'(/,a,/)')'the force constant matrix'
    1263              : !do ivarA=1,3*natom
    1264              : !write(std_out,'(/)')
    1265              : !do ivarB=1,3*natom
    1266              : !write(std_out,'(es16.6)')kmatrix(ivarB,ivarA)
    1267              : !end do
    1268              : !end do
    1269              : !ENDDEBUG
    1270              : 
    1271          200 :  Nmatr(:,:)=0.0_dp
    1272            8 :  do ivarB=0,natom-1
    1273           28 :    do ivarA=0,natom-1
    1274           20 :      Nmatr(3*ivarA+1,3*ivarB+1) = one
    1275           20 :      Nmatr(3*ivarA+2,3*ivarB+2) = one
    1276           26 :      Nmatr(3*ivarA+3,3*ivarB+3) = one
    1277              :    end do
    1278              :  end do
    1279              : 
    1280              : !DEBUG
    1281              : !do ivarA=1,3*natom
    1282              : !write(std_out,'(/)')
    1283              : !do ivarB=1,3*natom
    1284              : !write(std_out,'(es16.6)')Nmatr(ivarB,ivarA)
    1285              : !end do
    1286              : !end do
    1287              : !ENDDEBUG
    1288              : 
    1289              : !starting the pseudoinverting processes
    1290              : !then get the eigenvectors of the big matrix,give values to matrixBp
    1291          299 :  Bpmatr=0.0_dp
    1292              :  ii1=1
    1293           20 :  do ivarA=1,3*natom
    1294          119 :    do ivarB=1,ivarA
    1295           99 :      Bpmatr(1,ii1)=Nmatr(ivarB,ivarA)
    1296          117 :      ii1=ii1+1
    1297              :    end do
    1298              :  end do
    1299              : 
    1300              : !Bpmatr(2,:) is the imaginary part of the force matrix
    1301              : !then call the subroutines CHPEV and ZHPEV to get the eigenvectors
    1302            2 :  call ZHPEV ('V','U',3*natom,Bpmatr,eigvalp,eigvecp,3*natom,zhpev1p,zhpev2p,ier)
    1303            2 :  ABI_CHECK(ier == 0, sjoin("ZHPEV returned:", itoa(ier)))
    1304              : 
    1305              : !DEBUG
    1306              : !the eigenval and eigenvec
    1307              : !write(std_out,'(/,a,/)')'the eigenvalues and eigenvectors'
    1308              : !do ivarA=1,3*natom
    1309              : !write(std_out,'(/)')
    1310              : !write(std_out,'(es16.6)')eigvalp(ivarA)
    1311              : !end do
    1312              : !do ivarA=1,3*natom
    1313              : !write(std_out,'(/)')
    1314              : !do ivarB=1,3*natom
    1315              : !write(std_out,'(es16.6)')eigvecp(1,ivarB,ivarA)
    1316              : !end do
    1317              : !end do
    1318              : !ENDDEBUG
    1319              : 
    1320              : !Then do the multiplication to get the reduced matrix,in two steps
    1321              : !After this the force constant matrix is decouple in two bloks,
    1322              : !acoustic and optical ones
    1323         6632 :  Apmatr(:,:) = MATMUL(TRANSPOSE(eigvecp(1,:,:)), MATMUL(kmatrix, eigvecp(1,:,:)))
    1324              : 
    1325              : !DEBUG
    1326              : !the blok diago
    1327              : !write(std_out,'(/,a,/)')'matrixAp'
    1328              : !do ivarA=1,3*natom
    1329              : !write(std_out,'(/)')
    1330              : !do ivarB=1,3*natom
    1331              : !write(std_out,'(es16.6)')Apmatr(ivarA,ivarB)
    1332              : !end do
    1333              : !end do
    1334              : !ENDDEBUG
    1335              : 
    1336              : !Check the last three eigenvalues whether too large or not
    1337            2 :  ivarB=0
    1338            8 :  do ivarA=3*natom-2,3*natom
    1339            8 :    if (ABS(Apmatr(ivarA,ivarA))>tol6)then
    1340            0 :      ivarB=1
    1341              :    end if
    1342              :  end do
    1343              : 
    1344            2 :  if(ivarB==1)then
    1345            0 :    write(message,'(a,a,a,a,a,a,a,a,3es16.6)')ch10,&
    1346            0 : &   '  Acoustic sum rule violation met : the eigenvalues of accoustic mode',ch10,&
    1347            0 : &   '  are too large at Gamma point.',ch10,&
    1348            0 : &   '  Increase cutoff energy or k-points sampling.',ch10,&
    1349            0 : &   '  The three eigenvalues are:',Apmatr(3*natom-2,3*natom-2),Apmatr(3*natom-1,natom-1),Apmatr(3*natom,3*natom)
    1350            0 :    ABI_WARNING(message)
    1351            0 :    call wrtout(iout,message,'COLL')
    1352              :  end if
    1353              : 
    1354              : !Give the value of reduced matrix form Apmatr to Amatr
    1355          104 :  Amatr(:,:) = Apmatr(1:3*natom-3, 1:3*natom-3)
    1356              : 
    1357              : !Now the reduced matrix is in the matrixA, the convert it
    1358              : !first give the give the value of matixB from matrixA
    1359              :  ii1=1
    1360           14 :  do ivarA=1,3*natom-3
    1361           65 :    do ivarB=1,ivarA
    1362           51 :      Bmatr(1,ii1)=Amatr(ivarB,ivarA)
    1363           63 :      ii1=ii1+1
    1364              :    end do
    1365              :  end do
    1366           53 :  Bmatr(2,:)=0.0_dp
    1367              : 
    1368              : !Call the subroutines CHPEV and ZHPEV to get the eigenvectors and the eigenvalues
    1369            2 :  call ZHPEV ('V','U',3*natom-3,Bmatr,eigval,eigvec,3*natom-3,zhpev1,zhpev2,ier)
    1370            2 :  ABI_CHECK(ier == 0, sjoin("ZHPEV returned:", itoa(ier)))
    1371              : 
    1372              : !Check the unstable phonon modes, if the first is negative then print
    1373              : !warning message
    1374            2 :  if(eigval(1)<-1.0*tol8)then
    1375            0 :    write(message,'(9a)') ch10,&
    1376            0 : &   ' --- !WARNING',ch10,&
    1377            0 : &   '     Unstable eigenvalue detected in force constant matrix at Gamma point',ch10,&
    1378            0 : &   '     The system under calculation is physically unstable.',ch10,&
    1379            0 : &   ' ---',ch10
    1380            0 :    call wrtout(std_out,message,'COLL')
    1381              :  end if
    1382              : 
    1383              : !Do the matrix mutiplication to get pseudoinverse inverse matrix
    1384          104 :  Amatr(:,:)=0.0_dp
    1385           14 :  do ivarA=1,3*natom-3
    1386           14 :    Amatr(ivarA,ivarA)=1.0_dp/eigval(ivarA)
    1387              :  end do
    1388              : 
    1389         2684 :  Cmatr(:,:) = MATMUL(eigvec(1,:,:), MATMUL(Amatr, TRANSPOSE(eigvec(1,:,:))))
    1390              : 
    1391              : !DEBUG
    1392              : !write(std_out,'(/,a,/)')'the pseudo inverse of the force matrix'
    1393              : !do ivarA=1,3*natom
    1394              : !write(std_out,'(/)')
    1395              : !do ivarB=1,3*natom
    1396              : !write(std_out,'(es16.6)')Cmatr(ivarA,ivarB)
    1397              : !end do
    1398              : !end do
    1399              : !ENDDEBUG
    1400              : 
    1401              : !So now the inverse of the reduced matrix is in the matrixC
    1402              : !now do another mutilplication to get the pseudoinverse of the original
    1403          200 :  Cpmatr(:,:)=0.0_dp
    1404          104 :  Cpmatr(1:3*natom-3,1:3*natom-3) = Cmatr(:,:)
    1405              : 
    1406         6632 :  Apmatr(:,:) = MATMUL(eigvecp(1,:,:), MATMUL(Cpmatr, TRANSPOSE(eigvecp(1,:,:))))
    1407              : 
    1408              : !Now the inverse is in Cpmatr
    1409          200 :  kmatrix(:,:)=Apmatr(:,:)
    1410              : !transfer the inverse of k-matrix back to the k matrix
    1411              : !so now the inverse of k matrix is in the kmatrix
    1412              : !ending the part for pseudoinversing the K matrix
    1413              : 
    1414              :  DBG_EXIT("COLL")
    1415              : 
    1416            2 :  end subroutine dm_psinv
    1417              : !!***
    1418              : 
    1419              : !!****f* ABINIT/m_ddb_flexo/ddb_phi1
    1420              : !! NAME
    1421              : !!  ddb_phi1
    1422              : !!
    1423              : !! FUNCTION
    1424              : !! Return the moment of IFCs Phi^(1) and \sum_k Phi^(2)
    1425              : !!
    1426              : !! INPUTS
    1427              : !!  ddb<type(ddb_type)>=Long wave 3rd order derivative database.
    1428              : !!  ddb_version = 8 digit integer giving date. To mantain compatibility with old DDB files.
    1429              : !!  Crystal<type(crystal_t)>=Crystal structure parameters
    1430              : !!  filnamddb = name of the ddb file
    1431              : !!
    1432              : !! OUTPUT
    1433              : !!  phi1(3,natom,3,natom,3)=First Moment of IFCs Phi^(1)
    1434              : !!  phi2(3,natom,3,3,3)=Second Moment of IFCs Phi^(2) summed over atoms
    1435              : !!
    1436              : !! SIDE EFFECTS
    1437              : !!
    1438              : !! NOTES
    1439              : !!
    1440              : !! SOURCE
    1441              : 
    1442            1 : subroutine ddb_phi1(ddb,ddb_lw,ddb_version,filnamddb,phi1,phi2,natom)
    1443              : 
    1444              :  implicit none
    1445              : 
    1446              : !Arguments ------------------------------------
    1447              : !scalars
    1448              :  integer,intent(in) :: ddb_version, natom
    1449              :  class(ddb_type),intent(in) :: ddb,ddb_lw
    1450              :  character(len=fnlen) :: filnamddb
    1451              : !arrays
    1452              :  real(dp), intent(out) :: phi1(3,natom,3,natom,3)
    1453              :  real(dp), intent(out) :: phi2(3,natom,3,3,3)
    1454              : 
    1455              : !Local variables-------------------------------
    1456              :  integer,parameter :: cvrsio8=20100401
    1457              :  integer :: iblok,istrs,strsd1,strsd2,strst,strsd,qvecd
    1458              :  character(len=500) :: msg
    1459              : 
    1460              : !arrays
    1461              :  integer :: rfelfd(4),rfphon(4),rfstrs(4),iat,iatd
    1462              :  integer,parameter :: alpha(6)=(/1,2,3,2,1,1/),beta(6)=(/1,2,3,3,3,2/)
    1463              :  integer :: rfqvec(4)
    1464              :  real(dp) :: qphnrm(3),qphon(3,3),fac
    1465            2 :  real(dp) :: sqrbkt_t1(3,natom,3,3,3)
    1466            2 :  real(dp) :: d3cart(2,3,ddb%mpert,3,ddb%mpert,3,ddb%mpert)
    1467            2 :  real(dp) :: phi2tmp(3,ddb%mpert,3,3,3)
    1468              : 
    1469              : ! *********************************************************************
    1470              : 
    1471              :  DBG_ENTER("COLL")
    1472              : 
    1473            1 :  qphon(:,:)=zero
    1474            4 :  qphnrm(:)=one
    1475            1 :  rfphon(:)=0
    1476            1 :  rfelfd(:)=0
    1477            1 :  rfstrs(:)=0
    1478            1 :  rfqvec(:)=0
    1479              :  
    1480            1 :  rfphon(1)=1
    1481            1 :  rfphon(2)=1
    1482            1 :  rfqvec(3)=1
    1483              : 
    1484            1 :  write(msg, '(2a)' ) ch10," Extract the Phi^(1) coeficients from 3DTE"
    1485            1 :  call wrtout(std_out,msg,'COLL')
    1486            1 :  call ddb_lw%get_block(iblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,BLKTYP_d3E_lw,rfqvec=rfqvec)
    1487              : 
    1488            1 :  if (iblok == 0) then
    1489            0 :    call wrtout(std_out, "  ")
    1490            0 :    call wrtout(std_out, "--- !WARNING")
    1491            0 :    call wrtout(std_out, sjoin("- Cannot find Phi^(1) tensor in DDB file:", filnamddb))
    1492            0 :    call wrtout(std_out, "  flexoflag=1 or 3 requires the DDB file to include the corresponding long wave 3rd derivatives")
    1493              :  end if
    1494              : 
    1495       251339 :  d3cart(1,:,:,:,:,:,:) = reshape(ddb_lw%val(1,:,iblok),shape = (/3,ddb%mpert,3,ddb%mpert,3,ddb%mpert/))
    1496       251339 :  d3cart(2,:,:,:,:,:,:) = reshape(ddb_lw%val(2,:,iblok),shape = (/3,ddb%mpert,3,ddb%mpert,3,ddb%mpert/))
    1497              : 
    1498              : !Define the factors to apply if DDB file has been created with the old version of
    1499              : !the longwave driver.
    1500            1 :  if (ddb_version <= cvrsio8) then
    1501              :    fac=two
    1502              :  else
    1503            0 :    fac=one
    1504              :  end if
    1505              : 
    1506              : !Extraction of dC/dq and d2C/dqdq
    1507              :  phi1(:,:,:,:,:) = fac*RESHAPE(d3cart(2,1:3,1:ddb%natom,1:3,1:ddb%natom,1:3,ddb%natom+8), &
    1508          634 :                                & SHAPE=[3,ddb%natom,3,ddb%natom,3]) 
    1509              : 
    1510              : !Define the factors to apply if DDB file has been created with the old version of
    1511              : !the longwave driver. Note that there is a factor -1 to go to the derivatives
    1512            1 :  if (ddb_version <= cvrsio8) then
    1513              :    fac=two
    1514              :  else
    1515            0 :    fac=-one
    1516              :  end if
    1517              : 
    1518          472 :  phi2 = zero
    1519            7 :  do istrs=1,6
    1520            6 :    strsd1=alpha(istrs)
    1521            6 :    strsd2=beta(istrs)
    1522            6 :    strst=ddb%natom+3; if (istrs>3) strst=ddb%natom+4
    1523            3 :    strsd=istrs; if (istrs>3) strsd=istrs-3
    1524           25 :    do qvecd=1,3
    1525           96 :      do iat=1,ddb%natom
    1526          306 :        do iatd=1,3
    1527          216 :          phi2tmp(iatd,iat,qvecd,strsd1,strsd2)=fac*d3cart(1,iatd,iat,strsd,strst,qvecd,ddb%natom+8)
    1528          288 :          if (istrs>3) phi2tmp(iatd,iat,qvecd,strsd2,strsd1)=phi2tmp(iatd,iat,qvecd,strsd1,strsd2)
    1529              :        end do
    1530              :      end do
    1531              :    end do
    1532              :  end do    
    1533            4 : do qvecd=1,3
    1534           13 :    do strsd2=1,3
    1535           39 :      do strsd1=1,3
    1536          144 :        do iat=1,ddb%natom
    1537              :          sqrbkt_t1(1:3,iat,strsd1,strsd2,qvecd)=half*(phi2tmp(1:3,iat,qvecd,strsd1,strsd2) + &
    1538          459 :          & phi2tmp(1:3,iat,strsd2,strsd1,qvecd))
    1539              :        end do
    1540              :      end do
    1541              :    end do
    1542              :  end do
    1543              : 
    1544              : !Now correct the stress in the square bracketed tesnor tensor
    1545              : ! do qvecd=1,3
    1546              : !   do strsd2=1,3
    1547              : !     do strsd1=1,3
    1548              : !       do iatd=1,3
    1549              : !         if (iatd==strsd1) then
    1550              : !           sqrbkt_t1(iatd,strsd1,strsd2,qvecd)=sqrbkt_t1(iatd,strsd1,strsd2,qvecd) - stress(strsd2,qvecd)
    1551              : !         endif
    1552              : !       end do
    1553              : !     end do
    1554              : !   end do
    1555              : ! end do
    1556              : 
    1557              : !Now convert back to type-II in order to obtain the frozen ion Lagrange elastic tensor.
    1558          472 :  phi2(:,:,:,:,:)=zero
    1559            4 :  do iatd=1,3
    1560           13 :    do qvecd=1,3
    1561           39 :      do strsd1=1,3
    1562          117 :        do strsd2=1,3
    1563          432 :          do iat=1,ddb%natom
    1564              :            phi2(iatd,iat,qvecd,strsd1,strsd2)=sqrbkt_t1(iatd,iat,strsd1,qvecd,strsd2) + &
    1565          405 :          & sqrbkt_t1(iatd,iat,strsd2,strsd1,qvecd)-sqrbkt_t1(iatd,iat,qvecd,strsd2,strsd1)
    1566              :          end do
    1567              :        end do
    1568              :      end do
    1569              :    end do
    1570              :  end do
    1571              :  DBG_EXIT("COLL")
    1572            1 :  end subroutine ddb_phi1
    1573              :  !!***
    1574            6 : end module m_ddb_flexo
        

Generated by: LCOV version 2.3-1