LCOV - code coverage report
Current view: top level - src/77_ddb - m_harmonic_thermo.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 95.0 % 505 480
Test Date: 2026-11-09 12:18:26 Functions: 100.0 % 1 1
Branches: 70.7 % 784 554

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_harmonic_thermo
       2                 :             : !! NAME
       3                 :             : !! m_harmonic_thermo
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !! This routine to calculate phonon density of states,
       7                 :             : !! thermodynamical properties, Debye-Waller factor, and atomic mean square velocity
       8                 :             : !!
       9                 :             : !! COPYRIGHT
      10                 :             : !!  Copyright (C) 2008-2026 ABINIT group (CL, XG)
      11                 :             : !!  This file is distributed under the terms of the
      12                 :             : !!  GNU General Public License, see ~abinit/COPYING
      13                 :             : !!  or http://www.gnu.org/copyleft/gpl.txt .
      14                 :             : !!
      15                 :             : !! SOURCE
      16                 :             : 
      17                 :             : #if defined HAVE_CONFIG_H
      18                 :             : #include "config.h"
      19                 :             : #endif
      20                 :             : 
      21                 :             : #include "abi_common.h"
      22                 :             : 
      23                 :             : module m_harmonic_thermo
      24                 :             : 
      25                 :             :  use defs_basis
      26                 :             :  use m_errors
      27                 :             :  use m_abicore
      28                 :             :  use m_sortph
      29                 :             :  use m_xmpi
      30                 :             : 
      31                 :             :  use m_io_tools,       only : open_file
      32                 :             :  use m_matrix,         only : matr3inv
      33                 :             :  use m_dynmat,         only : gtdyn9
      34                 :             :  use m_geometry,       only : mkrdim
      35                 :             :  use m_crystal,        only : crystal_t
      36                 :             :  use m_anaddb_dataset, only : anaddb_dataset_type
      37                 :             :  use m_ifc,            only : ifc_type
      38                 :             :  use m_kpts,           only : smpbz
      39                 :             :  use m_symkpt,         only : symkpt
      40                 :             : 
      41                 :             :  implicit none
      42                 :             : 
      43                 :             :  private
      44                 :             : !!***
      45                 :             : 
      46                 :             :  public :: harmonic_thermo
      47                 :             : !!***
      48                 :             : 
      49                 :             : contains
      50                 :             : !!***
      51                 :             : 
      52                 :             : !!****f* m_harmonic_thermo/harmonic_thermo
      53                 :             : !!
      54                 :             : !! NAME
      55                 :             : !! harmonic_thermo
      56                 :             : !!
      57                 :             : !! FUNCTION
      58                 :             : !! This routine to calculate phonon density of states,
      59                 :             : !! thermodynamical properties, Debye-Waller factor, and atomic mean square velocity
      60                 :             : !!
      61                 :             : !! INPUTS
      62                 :             : !! Crystal<crystal_t>=data type gathering info on the crystalline structure.
      63                 :             : !! Ifc<ifc_type>=Object containing the interatomic force constants.
      64                 :             : !!    %atmfrc(2,3,natom,3,natom,nrpt) = Interatomic Forces in real space
      65                 :             : !!    %dyewq0(3,3,natom)=Ewald part of the dynamical matrix, at q=0.
      66                 :             : !!    %rpt(3,nrpt)=canonical coordinates of the R points in the unit cell These coordinates are normalized (=> * acell(3)!!)
      67                 :             : !!    %nrpt=number of R points in the Big Box
      68                 :             : !!    %trans(3,natom)=atomic translations : xred = rcan + trans
      69                 :             : !!    %wghatm(natom,natom,nrpt)=weights associated to a pair of atoms and to a R vector
      70                 :             : !! amu(ntypat)=mass of the atoms (atomic mass unit)
      71                 :             : !! anaddb_dtset= (derived datatype) contains all the input variables
      72                 :             : !! iout =unit number for output
      73                 :             : !! natom=number of atoms in the unit cell
      74                 :             : !! outfilename_radix=radix of anaddb output file name: append _THERMO for thermodynamic quantities
      75                 :             : !! comm=MPI communicator
      76                 :             : !!
      77                 :             : !! OUTPUT
      78                 :             : !!
      79                 :             : !! NOTES
      80                 :             : !! dosinc=increment between the channels for the phonon DOS in cm-1
      81                 :             : !!
      82                 :             : !! SOURCE
      83                 :             : 
      84                 :           4 : subroutine harmonic_thermo(Ifc,Crystal,amu,anaddb_dtset,iout,outfilename_radix,comm,thmflag)
      85                 :             : 
      86                 :             : !Arguments -------------------------------
      87                 :             : !scalars
      88                 :             :  integer,intent(in) :: iout,comm
      89                 :             :  integer,intent(in),optional :: thmflag
      90                 :             :  character(len=*),intent(in) :: outfilename_radix
      91                 :             :  type(anaddb_dataset_type),intent(in) :: anaddb_dtset
      92                 :             :  type(crystal_t),intent(in) :: Crystal
      93                 :             :  type(ifc_type),intent(in) :: Ifc
      94                 :             : !arrays
      95                 :             :  real(dp),intent(in) :: amu(Crystal%ntypat)
      96                 :             : 
      97                 :             : !Local variables -------------------------
      98                 :             : !scalars
      99                 :             :  integer,parameter :: master=0
     100                 :             :  integer :: convth,facbrv,iatom,ichan,icomp,igrid,iii,iiii,ij,ind
     101                 :             :  integer :: iqpt2,isym,itemper,iwchan,jjj,mqpt2,nchan,ngrids,natom
     102                 :             :  integer :: nqpt2,nspqpt,ntemper,nwchan,option,timrev
     103                 :             :  integer :: thermal_unit
     104                 :             :  integer :: bij_unit
     105                 :             :  integer :: vij_unit
     106                 :             :  integer :: nomega, iomega
     107                 :             :  real(dp) :: change,cothx,diffbb,dosinc,expm2x,factor,factorw,factorv,gerr
     108                 :             :  real(dp) :: ggsum,ggsumsum,ggrestsum
     109                 :             :  real(dp) :: gijerr,gijsum,gnorm,ln2shx,qphnrm,relchg,tmp,wovert,thmtol
     110                 :             :  logical :: part1,part2
     111                 :             :  character(len=500) :: msg
     112                 :             :  character(len=fnlen) :: thermal_filename
     113                 :             :  character(len=fnlen) :: bij_filename
     114                 :             :  character(len=fnlen) :: vij_filename
     115                 :             : !arrays
     116                 :           8 :  integer :: symrec(3,3,Crystal%nsym),symrel(3,3,Crystal%nsym)
     117                 :           8 :  real(dp) :: symrec_cart(3,3,Crystal%nsym)
     118                 :             :  integer :: igqpt2(3),ii(6),jj(6),qptrlatt(3,3)
     119                 :           4 :  integer,allocatable :: indqpt1(:),nchan2(:),bz2ibz_smap(:,:)
     120                 :             :  real(dp) :: gprimd(3,3),qphon(3),rprimd(3,3),tens1(3,3),tens2(3,3)
     121                 :           8 :  real(dp) :: displ(2*3*Crystal%natom*3*Crystal%natom)
     122                 :           8 :  real(dp) :: eigvec(2,3,Crystal%natom,3*Crystal%natom)
     123         [ +  - ]:           4 :  real(dp) :: phfrq(3*Crystal%natom)
     124                 :           4 :  real(dp),allocatable :: bbij(:,:,:),bij(:,:,:),energy(:),energy0(:),entropy(:)
     125                 :           4 :  real(dp),allocatable :: entropy0(:),free(:),free0(:),gdos(:,:),gg(:,:),gg_sum(:,:),gg_rest(:,:)
     126                 :           4 :  real(dp),allocatable :: ggij(:,:,:,:),gij(:,:,:,:),gw(:,:),qpt2(:,:),spheat(:)
     127                 :           4 :  real(dp),allocatable :: spheat0(:),spqpt2(:,:),wme(:),wtq(:),wtq2(:)
     128                 :           4 :  real(dp),allocatable :: wtq_folded(:),vij(:,:,:)
     129                 :           4 :  real(dp),allocatable :: phon_dos(:)
     130                 :           4 :  logical,allocatable :: wgcnv(:),wgijcnv(:)
     131                 :             : 
     132                 :             : ! *********************************************************************
     133                 :             : 
     134                 :             :  ! For the time being, this routine can use only 1 MPI process
     135         [ +  - ]:           4 :  if (xmpi_comm_rank(comm) /= master) return
     136                 :             : 
     137                 :           4 :  natom = Crystal%natom
     138   [ +  +  +  +  :         784 :  symrel = Crystal%symrel
                   +  + ]
     139   [ +  +  +  +  :         784 :  symrec = Crystal%symrec
                   +  + ]
     140                 :             : 
     141                 :           4 :  call mkrdim(Ifc%acell,Ifc%rprim,rprimd)
     142                 :           4 :  call matr3inv(rprimd,gprimd)
     143         [ +  + ]:          64 :  do isym = 1, Crystal%nsym
     144   [ +  +  +  +  :        6184 :    symrec_cart(:,:,isym) = matmul( gprimd, matmul(dble(symrec(:,:,isym)), transpose(rprimd)) )
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
                      + ]
     145                 :             : ! net result is tens1 = rprimd symrec^T gprimd^T   tens1   gprimd symrec rprimd^T
     146                 :             :  end do
     147                 :             : 
     148         [ +  - ]:           4 :  thermal_filename=trim(outfilename_radix)//"_THERMO"
     149         [ -  + ]:           4 :  if (open_file(thermal_filename, msg, newunit=thermal_unit) /= 0) then
     150                 :           0 :    ABI_ERROR(msg)
     151                 :             :  end if
     152                 :             : 
     153                 :           4 :  write(thermal_unit,*) '#'
     154                 :           4 :  write(thermal_unit,*) '#  Thermodynamical quantities calculated by ANADDB'
     155                 :           4 :  write(thermal_unit,*) '#'
     156                 :             : 
     157         [ +  - ]:           4 :  bij_filename=trim(outfilename_radix)//"_DEBYE_WALLER"
     158         [ -  + ]:           4 :  if (open_file(bij_filename, msg, newunit=bij_unit) /= 0) then
     159                 :           0 :    ABI_ERROR(msg)
     160                 :             :  end if
     161                 :             : 
     162         [ +  - ]:           4 :  vij_filename=trim(outfilename_radix)//"_VELOC_SQUARED"
     163         [ -  + ]:           4 :  if (open_file(vij_filename, msg, newunit=vij_unit) /= 0) then
     164                 :           0 :    ABI_ERROR(msg)
     165                 :             :  end if
     166                 :             : 
     167                 :           4 :  thmtol = anaddb_dtset%thmtol
     168                 :           4 :  nchan=anaddb_dtset%nchan
     169                 :           4 :  ntemper=anaddb_dtset%ntemper
     170                 :           4 :  nwchan=anaddb_dtset%nwchan
     171                 :           4 :  ngrids=anaddb_dtset%ngrids
     172                 :             : 
     173   [ -  +  +  -  :          16 :  ABI_MALLOC(bbij,(6,natom,ntemper))
          -  +  +  -  +  
          -  +  -  -  +  
                   -  + ]
     174   [ -  +  +  -  :          12 :  ABI_MALLOC(bij,(6,natom,ntemper))
          -  +  +  -  -  
                +  -  + ]
     175   [ -  +  +  -  :          12 :  ABI_MALLOC(vij,(6,natom,ntemper))
          -  +  +  -  -  
                +  -  + ]
     176   [ -  +  +  -  :          12 :  ABI_MALLOC(energy,(ntemper))
          +  -  +  -  -  
                +  -  + ]
     177   [ -  +  +  -  :           8 :  ABI_MALLOC(energy0,(ntemper))
             -  +  -  + ]
     178   [ -  +  +  -  :           8 :  ABI_MALLOC(entropy,(ntemper))
             -  +  -  + ]
     179   [ -  +  +  -  :           8 :  ABI_MALLOC(entropy0,(ntemper))
             -  +  -  + ]
     180   [ -  +  +  -  :           8 :  ABI_MALLOC(free,(ntemper))
             -  +  -  + ]
     181   [ -  +  +  -  :           8 :  ABI_MALLOC(free0,(ntemper))
             -  +  -  + ]
     182                 :             : !Doubling the size (nchan) of gg_sum is needed, because the maximum sum frequency is the double
     183                 :             : !the for maximum frequency. However, for the write statement, it is better to double
     184                 :             : !also the size of the other arrays ...
     185   [ +  -  -  +  :          16 :  ABI_MALLOC(gdos,(2*nchan,nwchan))
          +  -  -  +  +  
          -  +  -  +  -  
             -  +  -  + ]
     186   [ -  +  +  -  :          12 :  ABI_MALLOC(gg,(2*nchan,nwchan))
          -  +  +  -  -  
                +  -  + ]
     187   [ -  +  +  -  :          12 :  ABI_MALLOC(gg_sum,(2*nchan,nwchan))
          -  +  +  -  -  
                +  -  + ]
     188   [ -  +  +  -  :          12 :  ABI_MALLOC(gg_rest,(2*nchan,nwchan))
          -  +  +  -  -  
                +  -  + ]
     189   [ -  +  +  -  :          20 :  ABI_MALLOC(ggij,(6,natom,nchan,nwchan))
          -  +  +  -  -  
          +  +  -  +  -  
          +  -  -  +  -  
                      + ]
     190   [ -  +  +  -  :          16 :  ABI_MALLOC(gij,(6,natom,nchan,nwchan))
          -  +  +  -  -  
          +  +  -  -  +  
                   -  + ]
     191   [ -  +  +  -  :          12 :  ABI_MALLOC(nchan2,(nwchan))
          +  -  +  -  -  
                +  -  + ]
     192   [ -  +  +  -  :           8 :  ABI_MALLOC(spheat,(ntemper))
             -  +  -  + ]
     193   [ -  +  +  -  :           8 :  ABI_MALLOC(spheat0,(ntemper))
             -  +  -  + ]
     194   [ -  +  +  -  :           8 :  ABI_MALLOC(wgcnv,(nwchan))
             -  +  -  + ]
     195   [ -  +  +  -  :           8 :  ABI_MALLOC(wgijcnv,(nwchan))
             -  +  -  + ]
     196   [ -  +  +  -  :           8 :  ABI_MALLOC(wme,(ntemper))
             -  +  -  + ]
     197   [ -  +  +  -  :          16 :  ABI_MALLOC(gw,(nchan,nwchan))
          -  +  +  -  +  
          -  +  -  -  +  
                   -  + ]
     198                 :             : 
     199                 :             : 
     200                 :             : !initialize ii and jj arrays
     201                 :           4 :  ii(1)=1 ; ii(2)=2 ; ii(3)=3
     202                 :           4 :  ii(4)=1 ; ii(5)=1 ; ii(6)=2
     203                 :           4 :  jj(1)=1 ; jj(2)=2 ; jj(3)=3
     204                 :           4 :  jj(4)=2 ; jj(5)=3 ; jj(6)=3
     205                 :             : 
     206                 :             : !Put zeros in the bins of channels of frequencies
     207   [ +  +  +  + ]:       53529 :  gdos(:,:)=0._dp
     208   [ +  +  +  + ]:       53529 :  gg_sum(:,:)=0._dp
     209   [ +  +  +  + ]:       53529 :  gg_rest(:,:)=0._dp
     210   [ +  +  +  +  :     1013779 :  gij(:,:,:,:)=0._dp
             +  +  +  + ]
     211                 :             : 
     212                 :             : !Neither part1 nor part2 are assumed converged initially
     213                 :             : !None of the channel widths are assumed converged initially
     214                 :             : 
     215                 :          29 :  part1=.false.
     216                 :          29 :  part2=.false.
     217                 :             : 
     218         [ +  + ]:          29 :  wgcnv(:)=.false.
     219         [ +  + ]:          29 :  wgijcnv(:)=.false.
     220                 :             : 
     221                 :             : !Thermodynamic quantities are put to zero.
     222                 :             : !(If exactly zero, initial convergence tests will fail.)
     223                 :             : 
     224         [ +  + ]:          44 :  free0(:)=1.d-05
     225         [ +  + ]:          44 :  energy0(:)=1.d-05
     226         [ +  + ]:          44 :  entropy0(:)=1.d-05
     227         [ +  + ]:          44 :  spheat0(:)=1.d-05
     228   [ +  +  +  +  :        1584 :  bij(:,:,:)=1.d-05
                   +  + ]
     229   [ +  +  +  +  :        1584 :  vij(:,:,:)=1.d-05
                   +  + ]
     230                 :             : 
     231                 :             : !Number of actual channels set
     232         [ +  + ]:          29 :  do iwchan=1,nwchan
     233                 :          29 :    nchan2(iwchan)=(nchan-1)/iwchan+1
     234                 :             :  end do
     235                 :             : 
     236                 :             : !For different types of Bravais lattices
     237                 :           4 :  facbrv=1
     238         [ +  + ]:           4 :  if(anaddb_dtset%brav==2)facbrv=2
     239         [ -  + ]:           4 :  if(anaddb_dtset%brav==3)facbrv=4
     240                 :             : 
     241                 :             : !Loops on the q point grids
     242         [ +  + ]:          16 :  do igrid=1,ngrids
     243                 :             : 
     244         [ +  + ]:          56 :    igqpt2(:)=max((anaddb_dtset%ng2qpt(:)*igrid)/ngrids, 1)
     245                 :          14 :    mqpt2=(igqpt2(1)*igqpt2(2)*igqpt2(3))/facbrv
     246   [ -  +  +  -  :          42 :    ABI_MALLOC(qpt2,(3,mqpt2))
          +  -  +  -  -  
                +  -  + ]
     247   [ -  +  +  -  :          28 :    ABI_MALLOC(spqpt2,(3,mqpt2))
             -  +  -  + ]
     248                 :             : 
     249                 :          14 :    option=1
     250                 :          14 :    qptrlatt(:,:)=0
     251                 :          14 :    qptrlatt(1,1)=igqpt2(1)
     252                 :          14 :    qptrlatt(2,2)=igqpt2(2)
     253                 :          14 :    qptrlatt(3,3)=igqpt2(3)
     254                 :          14 :    call smpbz(anaddb_dtset%brav,iout,qptrlatt,mqpt2,nspqpt,1,option,anaddb_dtset%q2shft,spqpt2)
     255                 :             : 
     256   [ -  +  +  -  :          42 :    ABI_MALLOC(indqpt1,(nspqpt))
          +  -  +  -  -  
                +  -  + ]
     257   [ -  +  +  -  :          42 :    ABI_MALLOC(wtq,(nspqpt))
          +  -  +  -  -  
                +  -  + ]
     258   [ -  +  +  -  :          28 :    ABI_MALLOC(wtq_folded,(nspqpt))
             -  +  -  + ]
     259   [ -  +  +  -  :          42 :    ABI_MALLOC(bz2ibz_smap,(6, nspqpt))
          +  -  +  -  -  
                +  -  + ]
     260                 :             : 
     261                 :             : !  Reduce the number of such points by symmetrization
     262         [ +  + ]:       31918 :    wtq(:)=1.0_dp
     263                 :             : 
     264                 :          14 :    timrev=1
     265                 :             :    call symkpt(0,Crystal%gmet,indqpt1,ab_out,spqpt2,nspqpt,nqpt2,Crystal%nsym,symrec,timrev,wtq,wtq_folded, &
     266                 :          14 :      bz2ibz_smap, xmpi_comm_self)
     267                 :             : 
     268         [ -  + ]:          14 :    ABI_FREE(bz2ibz_smap)
     269                 :             : 
     270   [ -  +  +  -  :          42 :    ABI_MALLOC(wtq2,(nqpt2))
          +  -  +  -  -  
                +  -  + ]
     271         [ +  + ]:        1760 :    do iqpt2=1,nqpt2
     272                 :        1746 :      wtq2(iqpt2)=wtq_folded(indqpt1(iqpt2))
     273         [ +  + ]:        6998 :      qpt2(:,iqpt2)=spqpt2(:,indqpt1(iqpt2))
     274                 :             :      !write(std_out,*)' harmonic_thermo : iqpt2, wtq2 :',iqpt2,wtq2(iqpt2)
     275                 :             :    end do
     276         [ -  + ]:          14 :    ABI_FREE(wtq_folded)
     277                 :             : 
     278                 :             : !  Temporary counters are put zero.
     279                 :             : 
     280   [ +  +  +  + ]:      192609 :    gg(:,:)=zero
     281   [ +  +  +  +  :     2668859 :    ggij(:,:,:,:)=zero
             +  +  +  + ]
     282   [ +  +  +  + ]:       96359 :    gw(:,:)=zero
     283                 :             : 
     284                 :             : !  Sum over the sampled q points
     285         [ +  + ]:        1760 :    do iqpt2=1,nqpt2
     286                 :             : 
     287         [ +  + ]:        6984 :      qphon(:)=qpt2(:,iqpt2)
     288                 :        1746 :      qphnrm=1.0_dp
     289                 :             : 
     290                 :             :      ! Fourier Interpolation
     291                 :        1746 :      call ifc%fourq(Crystal,qphon,phfrq,displ,out_eigvec=eigvec)
     292                 :             : 
     293         [ -  + ]:        1746 :      if (present(thmflag)) then
     294         [ #  # ]:           0 :        if (thmflag ==2)then
     295                 :           0 :          call sortph(eigvec,displ,outfilename_radix,natom,phfrq)
     296                 :             :        end if
     297                 :             :      end if
     298                 :             : 
     299                 :             : !    Sum over the phonon modes
     300         [ +  + ]:       33782 :      do iii=1,3*natom
     301                 :             : 
     302                 :             : !      Slightly negative frequencies are put to zero
     303                 :             : !      Imaginary frequencies are also put to zero
     304         [ +  + ]:       32022 :        if(phfrq(iii)<0._dp) phfrq(iii)=0._dp
     305                 :             : 
     306                 :             : !      Note: frequencies are now in cm-1
     307                 :             : 
     308                 :             : !      Sort frequencies into channels of frequencies for each channel width of frequency
     309         [ +  + ]:      198432 :        do iwchan=nwchan,1,-1
     310         [ +  + ]:      198432 :          if (.not.wgcnv(iwchan))then
     311                 :      164874 :            dosinc=dble(iwchan)
     312                 :      164874 :            ichan=int(phfrq(iii)*Ha_cmm1/dosinc)+1
     313                 :             : 
     314         [ -  + ]:      164874 :            if(ichan>nchan2(iwchan)) then
     315                 :             :              write(msg, '(a,es16.6,a,a,a,i7,a,a,a)' )&
     316                 :           0 : &             'There is a phonon frequency,',phfrq(iii),' larger than the maximum one,',ch10,&
     317                 :           0 : &             'as defined by the number of channels of width 1 cm-1, nchan=',nchan,'.',ch10,&
     318                 :           0 : &             'Action: increase nchan (suggestion : double it).'
     319                 :           0 :              ABI_ERROR(msg)
     320                 :             :            end if
     321                 :             : 
     322                 :      164874 :            gg(ichan,iwchan)=gg(ichan,iwchan)+wtq2(iqpt2)
     323                 :             : 
     324                 :      164874 :            gw(ichan,iwchan)=gw(ichan,iwchan)+wtq2(iqpt2)*phfrq(iii)*Ha_cmm1
     325                 :             : 
     326                 :             : !          to calculate two phonon DOS for qshift = 0.0
     327         [ +  + ]:     4062828 :            do iiii=1,3*natom
     328         [ -  + ]:     3897954 :              if(phfrq(iiii)<0.d0) phfrq(iiii)=0.d0
     329                 :             : 
     330                 :     3897954 :              ichan=int(abs(phfrq(iii)+phfrq(iiii))*Ha_cmm1/dosinc)+1
     331                 :     3897954 :              gg_sum(ichan,iwchan)=gg_sum(ichan,iwchan)+wtq2(iqpt2)
     332                 :             : 
     333                 :     3897954 :              ichan=int(abs(phfrq(iii)-phfrq(iiii))*Ha_cmm1/dosinc)+1
     334                 :     4062828 :              gg_rest(ichan,iwchan)=gg_rest(ichan,iwchan)+wtq2(iqpt2)
     335                 :             :            end do ! end loop for iiii
     336                 :             : 
     337                 :             :          end if
     338                 :             :        end do
     339                 :             : 
     340         [ +  + ]:      200178 :        do iwchan=nwchan,1,-1
     341         [ +  + ]:      198432 :          if (.not.wgijcnv(iwchan))then
     342                 :             : 
     343                 :      105660 :            dosinc=dble(iwchan)
     344                 :      105660 :            ichan=int(phfrq(iii)*Ha_cmm1/dosinc)+1
     345                 :             : 
     346         [ -  + ]:      105660 :            if(ichan>nchan2(iwchan)) then
     347                 :             :              write(msg, '(a,a,a,a,a)' )&
     348                 :           0 : &             'Phonon frequencies larger than the maximum one,',ch10,&
     349                 :           0 : &             'as defined by the number of channels of width 1 cm-1.',ch10,&
     350                 :           0 : &             'Action: increase nchan (suggestion : double it).'
     351                 :           0 :              ABI_ERROR(msg)
     352                 :             :            end if
     353                 :             : 
     354         [ +  + ]:     1054080 :            do iatom=1,natom
     355         [ +  + ]:     6744600 :              do ij=1,6
     356                 :             :                ggij(ij,iatom,ichan,iwchan)=ggij(ij,iatom,ichan,iwchan)&
     357                 :             : &               +wtq2(iqpt2)*&
     358                 :             : &               (eigvec(1,ii(ij),iatom,iii)*eigvec(1,jj(ij),iatom,iii)+&
     359                 :     6638940 : &               eigvec(2,ii(ij),iatom,iii)*eigvec(2,jj(ij),iatom,iii) )
     360                 :             :              end do
     361                 :             :            end do
     362                 :             : 
     363                 :             :          end if
     364                 :             :        end do
     365                 :             : 
     366                 :             :      end do ! End of the sum over the phonon modes
     367                 :             :    end do ! End of the sum over q-points in the irreducible zone
     368                 :             : 
     369                 :             : !  deallocate sortph array
     370                 :          14 :    call end_sortph()
     371                 :             : 
     372                 :             : !  Symmetrize the gij
     373         [ +  + ]:       15264 :    do ichan=1,nchan
     374         [ +  + ]:      111514 :      do iwchan=nwchan,1,-1
     375         [ +  + ]:      463750 :        do iatom=1,natom
     376         [ +  + ]:     2668750 :          do ij=1,6
     377                 :             : !          Uses bbij as work space
     378                 :     2205000 :            bbij(ij,iatom,1)=ggij(ij,iatom,ichan,iwchan)
     379                 :     2572500 :            ggij(ij,iatom,ichan,iwchan)=0.0_dp
     380                 :             :          end do
     381                 :             :        end do
     382         [ +  + ]:      479000 :        do iatom=1,natom
     383         [ +  + ]:     5137500 :          do isym=1,Crystal%nsym
     384                 :             : !          Find the atom that will be applied on atom iatom
     385                 :     4770000 :            ind=Crystal%indsym(4,isym,iatom)
     386         [ +  + ]:    33390000 :            do ij=1,6
     387                 :    33390000 :              tens1(ii(ij),jj(ij))=bbij(ij,ind,1)
     388                 :             :            end do
     389                 :             : !          complete the 3x3 tensor from the upper triangle
     390                 :     4770000 :            tens1(2,1)=tens1(1,2)
     391                 :     4770000 :            tens1(3,1)=tens1(1,3)
     392                 :     4770000 :            tens1(3,2)=tens1(2,3)
     393                 :             : !          Here acomplishes the tensorial operations
     394                 :             : !!          make this a BLAS call, or better yet batch the whole thing?
     395                 :             : !          2) Apply the symmetry operation on both indices   USING symrec in
     396                 :             : !          cartesian coordinates
     397         [ +  + ]:    19080000 :            do iii=1,3
     398         [ +  + ]:    62010000 :              do jjj=1,3
     399                 :             :                tens2(iii,jjj)=tens1(iii,1)*symrec_cart(1,jjj,isym)&
     400                 :             : &               +tens1(iii,2)*symrec_cart(2,jjj,isym)&
     401                 :    57240000 : &               +tens1(iii,3)*symrec_cart(3,jjj,isym)
     402                 :             :              end do
     403                 :             :            end do
     404         [ +  + ]:    19080000 :            do jjj=1,3
     405         [ +  + ]:    62010000 :              do iii=1,3
     406                 :             :                tens1(iii,jjj)=tens2(1,jjj)*symrec_cart(1,iii,isym)&
     407                 :             : &               +tens2(2,jjj)*symrec_cart(2,iii,isym)&
     408                 :    57240000 : &               +tens2(3,jjj)*symrec_cart(3,iii,isym)
     409                 :             :              end do
     410                 :             :            end do
     411                 :             : ! net result is tens1 = rprimd symrec^T gprimd^T   tens1   gprimd symrec rprimd^T
     412                 :             : 
     413                 :             : !          This accumulates over atoms, to account for all symmetric ones
     414         [ +  + ]:    33757500 :            do ij=1,6
     415                 :    33390000 :              ggij(ij,iatom,ichan,iwchan)=ggij(ij,iatom,ichan,iwchan) + tens1(ii(ij),jj(ij))
     416                 :             :            end do
     417                 :             : 
     418                 :             :          end do
     419                 :             : !        Each one will be replicated nsym times in the end:
     420         [ +  + ]:     2668750 :          do ij=1,6
     421                 :     2572500 :            ggij(ij,iatom,ichan,iwchan)=ggij(ij,iatom,ichan,iwchan)/dble(Crystal%nsym)
     422                 :             :          end do
     423                 :             :        end do
     424                 :             :      end do
     425                 :             :    end do
     426                 :             : 
     427                 :          14 :    call wrtout(std_out,' harmonic_thermo: g(w) and gij(k|w) calculated given a q sampling grid.','COLL')
     428                 :             : 
     429                 :             : !  Sum up the counts in the channels to check the normalization
     430                 :             : !  and test convergence with respect to q sampling
     431                 :          14 :    gnorm=(igqpt2(1)*igqpt2(2)*igqpt2(3)*3*natom)/facbrv
     432                 :             : 
     433         [ +  - ]:          14 :    if(.not.part1)then
     434         [ +  + ]:          87 :      do iwchan=nwchan,1,-1
     435                 :             : 
     436                 :             :        !write(msg,'(a,i0)' )' harmonic_thermo : iwchan=',iwchan
     437                 :             :        !call wrtout(std_out,msg,'COLL')
     438                 :             : 
     439         [ +  + ]:          77 :        if (wgcnv(iwchan)) cycle
     440                 :             :        !call wrtout(std_out,' harmonic_thermo : compute g, f, e, s, c','COLL')
     441                 :             : 
     442                 :             : !      Calculate g(w) and F,E,S,C
     443                 :             : 
     444                 :          76 :        ggsum=0.0_dp
     445                 :          76 :        ggsumsum=0.0_dp
     446                 :          76 :        ggrestsum=0.0_dp
     447         [ +  + ]:       27881 :        do ichan=1,nchan2(iwchan)
     448                 :       27805 :          ggsum=ggsum+gg(ichan,iwchan)
     449                 :       27805 :          ggsumsum=ggsumsum+gg_sum(ichan,iwchan)
     450                 :       27881 :          ggrestsum=ggrestsum+gg_rest(ichan,iwchan)
     451                 :             :        end do
     452                 :             : 
     453         [ -  + ]:          76 :        if(ggsum/=gnorm)then
     454                 :             :          write(msg, '(a,es14.6,i6,a,a,es14.6,a)' )&
     455                 :           0 : &         'Frequencies are missing in g(w) : ggsum,iwchan=',ggsum,iwchan,ch10,&
     456                 :           0 : &         'gnorm=',gnorm,'.'
     457                 :           0 :          ABI_BUG(msg)
     458                 :             :        end if
     459                 :             : 
     460                 :             : !      Check if the density of states changed by more than dostol
     461                 :             : 
     462                 :          76 :        gerr=zero
     463         [ +  + ]:          76 :        if (ngrids>1) then
     464         [ +  + ]:       27630 :          do ichan=1,nchan2(iwchan)
     465                 :       27630 :            gerr=gerr+abs(gg(ichan,iwchan)/ggsum-gdos(ichan,iwchan))
     466                 :             :          end do
     467                 :             :        end if
     468                 :             : 
     469   [ +  +  +  - ]:          76 :        if(gerr>anaddb_dtset%dostol.and.ngrids>1) then
     470                 :          69 :          wgcnv(iwchan)=.false.
     471                 :             :        else
     472                 :           7 :          wgcnv(iwchan)=.true.
     473                 :             :        end if
     474                 :             : 
     475                 :             : !      g(w) is updated
     476         [ +  + ]:       27881 :        do ichan=1,nchan2(iwchan)
     477                 :       27805 :          gdos(ichan,iwchan)=gg(ichan,iwchan)/ggsum
     478                 :       27805 :          gg_sum(ichan,iwchan)=gg_sum(ichan,iwchan)/ggsumsum
     479                 :       27881 :          gg_rest(ichan,iwchan)=gg_rest(ichan,iwchan)/ggrestsum
     480                 :             :        end do
     481         [ +  + ]:       27881 :        do ichan=1,nchan2(iwchan)
     482                 :       27881 :          gw(ichan,iwchan)=gw(ichan,iwchan)/ggsum
     483                 :             :        end do
     484                 :             : 
     485                 :             : !      Write gerr for each q sampling and w width
     486                 :          76 :        write(msg,'(a,a,i3,3i6,f10.1,f10.5)') ch10, &
     487                 :         152 : &       'harmonic_thermo: iwchan,igqpt(:),norm,error=',iwchan,igqpt2(1),igqpt2(2),igqpt2(3),ggsum+tol8,gerr+tol10
     488                 :          76 :        call wrtout(std_out,msg,'COLL')
     489                 :             : 
     490                 :             : !      If the DOS with a channel width is newly converged,
     491                 :             : !      print it out and calculate the thermodynamic functions.
     492                 :          76 :        convth=0
     493         [ +  + ]:          76 :        if(wgcnv(iwchan)) then
     494         [ +  + ]:           7 :          if (ngrids==1) then
     495         [ -  + ]:           1 :            if (anaddb_dtset%dossum /= 0 ) then
     496                 :           0 :              write(msg,'(a65,i5,a16)') ' DOS, SUM AND DIFFERENCE OF TWO PHONON DOS with channel width= ',iwchan,':'
     497                 :             :            else
     498                 :           1 :              write(msg,'(a25,i5,a16)') ' DOS  with channel width=  ',iwchan,':'
     499                 :             :            end if
     500                 :             :          else
     501         [ +  + ]:           6 :            if (anaddb_dtset%dossum /= 0 ) then
     502                 :             :              write(msg,'(a65,i5,a16)')&
     503                 :           2 : &             ' DOS, SUM AND DIFFERENCE OF TWO PHONON DOS  with channel width= ',iwchan,' newly converged'
     504                 :             :            else
     505                 :           4 :              write(msg,'(a25,i5,a16)') ' DOS  with channel width=  ',iwchan,' newly converged'
     506                 :             :            end if
     507                 :             :          end if
     508                 :             : 
     509                 :           7 :          call wrtout(std_out,msg,'COLL')
     510                 :           7 :          call wrtout(iout,msg,'COLL')
     511         [ +  + ]:        1552 :          do ichan=1,nchan2(iwchan)
     512         [ +  + ]:        1545 :            if (anaddb_dtset%dossum /= 0 ) then
     513                 :         563 :              write(msg,'(i8,f11.1,3(f12.5,3x))') ichan,gg(ichan,iwchan)+tol10,&
     514                 :         563 : &             gdos(ichan,iwchan)+tol10, gg_sum(ichan,iwchan)*(3.0*natom*3.0*natom)+tol10, &
     515                 :        1126 : &             gg_rest(ichan,iwchan)*(3.0*natom*(3.0*natom-1))+tol10
     516                 :             :            else
     517                 :         982 :              write(msg,'(i8,f11.1,1x,f12.5)') ichan,gg(ichan,iwchan)+tol10,&
     518                 :        1964 : &             gdos(ichan,iwchan)+tol10
     519                 :             :            end if
     520                 :        1552 :            call wrtout(std_out,msg,'COLL')
     521                 :             :          end do
     522                 :             : 
     523         [ +  + ]:           7 :          if (ngrids>1) then
     524                 :           6 :            write(msg,'(a24,f10.5)')'   with maximal error = ',gerr+tol10
     525                 :           6 :            call wrtout(std_out,msg,'COLL')
     526                 :           6 :            call wrtout(iout,msg,'COLL')
     527                 :             :          end if
     528                 :             : 
     529                 :           7 :          nomega = nchan2(iwchan)
     530                 :           7 :          dosinc=dble(iwchan)
     531                 :             : 
     532   [ -  +  +  -  :          21 :          ABI_MALLOC(phon_dos,(nomega))
          +  -  +  -  -  
                +  -  + ]
     533   [ -  +  +  + ]:        1559 :          phon_dos = gdos(1:nomega,iwchan)
     534                 :             : 
     535                 :             : !Put zeroes for F, E, S, Cv
     536         [ +  + ]:          77 :          free(:)=zero
     537         [ +  + ]:          77 :          energy(:)=zero
     538         [ +  + ]:          77 :          entropy(:)=zero
     539         [ +  + ]:          77 :          spheat(:)=zero
     540         [ +  + ]:          77 :          wme(:)=zero
     541                 :             : 
     542         [ +  + ]:          77 :          do itemper=1,ntemper
     543                 :             : 
     544                 :          70 :            tmp=anaddb_dtset%tempermin+anaddb_dtset%temperinc*dble(itemper-1)
     545                 :             : !          The temperature (tmp) is given in Kelvin
     546         [ +  - ]:          70 :            if (tmp < tol6) cycle
     547                 :             : 
     548         [ +  + ]:       15520 :            do iomega=1,nomega
     549                 :             : 
     550                 :             : !            wovert= hbar*w / 2kT dimensionless
     551                 :       15450 :              wovert=dosinc*(dble(iomega)-0.5_dp)/Ha_cmm1/(2._dp*kb_HaK*tmp)
     552                 :       15450 :              expm2x=exp(-2.0_dp*wovert)
     553                 :       15450 :              ln2shx=wovert+log(1.0_dp-expm2x)
     554                 :       15450 :              cothx=(1.0_dp+expm2x)/(1.0_dp-expm2x)
     555                 :       15450 :              factor=dble(3*natom)*phon_dos(iomega)
     556                 :       15450 :              factorw=3*natom*gw(iomega,iwchan)
     557                 :             : 
     558                 :             : !            This matches the equations published in Lee & Gonze, PRB 51, 8610 (1995) [[cite:Lee1995]]
     559                 :       15450 :              free(itemper)=free(itemper) +factor*kb_HaK*tmp*ln2shx
     560                 :       15450 :              energy(itemper)=energy(itemper) + factor*kb_HaK*tmp*wovert*cothx
     561                 :       15450 :              entropy(itemper)=entropy(itemper) + factor*kb_HaK*(wovert*cothx - ln2shx)
     562                 :             : 
     563                 :             : !            The contribution is much lower than 1.0d-16 when wovert<100.0_dp
     564         [ +  - ]:       15450 :              if(wovert<100.0_dp)then
     565                 :       15450 :                spheat(itemper)=spheat(itemper)+factor*kb_HaK*wovert**2/sinh(wovert)**2
     566                 :             :              end if
     567                 :       15520 :              wme(itemper)=wme(itemper)+factorw*kb_HaK*wovert**2/sinh(wovert)**2
     568                 :             : 
     569                 :             :            end do ! iomega
     570                 :             : 
     571         [ +  - ]:          77 :            if (abs(spheat(itemper))>tol8) wme(itemper)=wme(itemper)/spheat(itemper)
     572                 :             :          end do ! itemper
     573         [ -  + ]:           7 :          ABI_FREE(phon_dos)
     574                 :             : 
     575                 :             : !        Check if the thermodynamic functions change within tolerance,
     576         [ +  + ]:           7 :          if (ngrids>1) then
     577                 :             :            write(msg,'(a,a,a)')&
     578                 :           6 : &           ' harmonic_thermo : check if the thermodynamic functions',ch10,&
     579                 :          12 : &           '    change within tolerance.'
     580                 :           6 :            call wrtout(std_out,msg,'COLL')
     581                 :           6 :            convth=1
     582                 :             : 
     583         [ +  + ]:          36 :            do itemper=1,ntemper
     584                 :          33 :              change=free(itemper)-free0(itemper)
     585                 :          33 :              relchg=change/free0(itemper)
     586   [ +  -  +  + ]:          33 :              if(change>1d-14*dble(mqpt2) .and. relchg>thmtol)then
     587                 :             :                write(msg,'(a,es14.4,a,a,es14.4)' )&
     588                 :           3 : &               ' harmonic_thermo : free energy relative changes ',relchg,ch10,&
     589                 :           6 : &               '        are larger than thmtol ',thmtol
     590                 :           3 :                call wrtout(std_out,msg,'COLL')
     591                 :           3 :                convth=0
     592                 :             :              end if
     593                 :          33 :              change=energy(itemper)-energy0(itemper)
     594                 :          33 :              relchg=change/energy0(itemper)
     595   [ +  +  +  + ]:          33 :              if(change>1d-14*dble(mqpt2) .and. relchg>thmtol)then
     596                 :             :                write(msg,'(a,es14.4,a,a,es14.4)' )&
     597                 :           3 : &               ' harmonic_thermo : energy relative changes ',relchg,ch10,&
     598                 :           6 : &               '        are larger than thmtol ',thmtol
     599                 :           3 :                call wrtout(std_out,msg,'COLL')
     600                 :           3 :                convth=0
     601                 :             :              end if
     602                 :          33 :              change=entropy(itemper)-entropy0(itemper)
     603                 :          33 :              relchg=change/entropy0(itemper)
     604   [ +  +  +  - ]:          33 :              if(change>1d-14*dble(mqpt2) .and. relchg>thmtol)then
     605                 :             :                write(msg,'(a,es14.4,a,a,es14.4)' )&
     606                 :           1 : &               ' harmonic_thermo : entropy relative changes ',relchg,ch10,&
     607                 :           2 : &               '        are larger than thmtol ',thmtol
     608                 :           1 :                call wrtout(std_out,msg,'COLL')
     609                 :           1 :                convth=0
     610                 :             :              end if
     611                 :          33 :              change=spheat(itemper)-spheat0(itemper)
     612                 :          33 :              relchg=change/spheat0(itemper)
     613   [ +  +  +  + ]:          33 :              if(change>1d-14*dble(mqpt2) .and. relchg>thmtol)then
     614                 :             :                write(msg,'(a,es14.4,a,a,es14.4)' )&
     615                 :           1 : &               ' harmonic_thermo : specific heat relative changes ',relchg,ch10,&
     616                 :           2 : &               '        are larger than thmtol ',thmtol
     617                 :           1 :                call wrtout(std_out,msg,'COLL')
     618                 :             :                convth=0
     619                 :             :              end if
     620                 :             : 
     621         [ +  + ]:          35 :              if(convth==0)exit
     622                 :             :            end do ! End of check if the thermodynamic functions change within tolerance
     623                 :             : 
     624                 :             :          else
     625                 :             :            convth=1
     626                 :             :          end if
     627                 :             : 
     628                 :             : !        Update F,E,S,C and eventually write them if converged
     629         [ +  + ]:           6 :          if(convth==1)then
     630                 :           4 :            part1=.true.
     631                 :           4 :            write(msg,'(a,a,a)') ch10,&
     632                 :           8 : &           ' # At  T     F(J/mol-c)     E(J/mol-c)     S(J/(mol-c.K)) C(J/(mol-c.K)) Omega_mean(cm-1)'
     633                 :           4 :            call wrtout(iout,msg,'COLL')
     634                 :           4 :            call wrtout(thermal_unit,msg,'COLL')
     635                 :           4 :            msg = ' # (A mol-c is the abbreviation of a mole-cell, that is, the'
     636                 :           4 :            call wrtout(iout,msg,'COLL')
     637                 :           4 :            call wrtout(thermal_unit,msg,'COLL')
     638                 :           4 :            msg = ' #  number of Avogadro times the atoms in a unit cell)'
     639                 :           4 :            call wrtout(iout,msg,'COLL')
     640                 :           4 :            call wrtout(thermal_unit,msg,'COLL')
     641                 :             : 
     642                 :             :            write(msg, '(a,a,a)' )&
     643                 :           4 : &           ' harmonic_thermo : thermodynamic functions have converged',ch10,&
     644                 :           8 : &           '     see main output file ...'
     645                 :           4 :            call wrtout(std_out,msg,'COLL')
     646                 :             :          end if
     647                 :             : 
     648         [ +  + ]:          77 :          do itemper=1,ntemper
     649                 :          70 :            free0(itemper)=free(itemper)
     650                 :          70 :            energy0(itemper)=energy(itemper)
     651                 :          70 :            entropy0(itemper)=entropy(itemper)
     652                 :          70 :            spheat0(itemper)=spheat(itemper)
     653                 :             : 
     654         [ +  + ]:          77 :            if(convth==1)then
     655                 :          40 :              tmp=anaddb_dtset%tempermin+anaddb_dtset%temperinc*dble(itemper-1)
     656                 :          40 :              write(msg,'(es11.3,5es15.7)') tmp+tol8,&
     657                 :          40 : &             Ha_eV*e_Cb*Avogadro*free(itemper),&
     658                 :          40 : &             Ha_eV*e_Cb*Avogadro*energy(itemper),&
     659                 :          40 : &             Ha_eV*e_Cb*Avogadro*entropy(itemper),&
     660                 :          40 : &             Ha_eV*e_Cb*Avogadro*spheat(itemper),&
     661                 :          80 : &             wme(itemper)
     662                 :          40 :              call wrtout(iout,msg,'COLL')
     663                 :          40 :              call wrtout(thermal_unit,msg,'COLL')
     664                 :             :            end if
     665                 :             :          end do
     666                 :             :        end if
     667                 :             : 
     668         [ +  + ]:          17 :        if(convth==1)exit
     669                 :             :      end do
     670                 :             :    end if
     671                 :             : 
     672         [ +  + ]:          14 :    if(.not.part2)then
     673                 :             :      ! Atomic temperature factor calculation
     674         [ +  + ]:          65 :      do iwchan=nwchan,1,-1
     675         [ +  + ]:          55 :        if (wgijcnv(iwchan))cycle
     676                 :             : 
     677                 :             :        ! Calculate gij(k|w) and Bij(k)
     678                 :             :        ! Check if the density of states changed by more than dostol
     679                 :          25 :        gijsum =zero
     680                 :          25 :        wgijcnv(iwchan)=.true.
     681         [ +  + ]:          25 :        if (ngrids>1) then
     682         [ +  + ]:          95 :          do iatom=1,natom
     683         [ +  + ]:         545 :            do ij=1,6
     684                 :         450 :              gijerr=zero
     685         [ +  + ]:      217020 :              do ichan=1,nchan2(iwchan)
     686                 :      216570 :                gijsum = gijsum + gij(ij,iatom,ichan,iwchan)
     687                 :             :                gijerr=gijerr&
     688                 :             : &               +abs(ggij(ij,iatom,ichan,iwchan)/gnorm&
     689                 :      217020 : &               -     gij(ij,iatom,ichan,iwchan))
     690                 :             :              end do
     691         [ -  + ]:         525 :              if(gijerr>anaddb_dtset%dostol) then
     692                 :           0 :                wgijcnv(iwchan)=.false.
     693                 :           0 :                exit
     694                 :             :              end if
     695                 :             :            end do
     696                 :             :          end do
     697                 :             :        else
     698                 :             :          gijerr=0.d0
     699                 :             :        end if
     700                 :             : 
     701                 :             : !      gij(k|w) is updated
     702                 :             : 
     703         [ +  + ]:       10935 :        do ichan=1,nchan2(iwchan)
     704         [ +  + ]:       72725 :          do iatom=1,natom
     705         [ +  + ]:      443440 :            do ij=1,6
     706                 :      432530 :              gij(ij,iatom,ichan,iwchan)=ggij(ij,iatom,ichan,iwchan)/(gnorm/(3*natom))
     707                 :             :            end do
     708                 :             : !if (iwchan==1) write (200+iatom,'(I6,6(E20.10,2x))') ichan, gij(1:6,iatom,ichan,iwchan)
     709                 :             :          end do
     710                 :             :        end do
     711                 :             : 
     712                 :             : !      Write gijerr for each q sampling and w width
     713                 :             : 
     714                 :          25 :        write(msg,'(a,a,i3,3i6,f10.5,f10.5)') ch10,&
     715                 :          25 : &       ' iwchan,igqpt(i),gijsum, gij error= ',&
     716                 :          50 : &       iwchan,igqpt2(1),igqpt2(2),igqpt2(3),gijsum,gijerr+tol10
     717                 :          25 :        call wrtout(std_out,msg,'COLL')
     718                 :             : 
     719                 :             : !      If the generalized DOS with a channel width is newly converged,
     720                 :             : !      print it out and calculate Bij(k).
     721         [ +  - ]:          35 :        if(wgijcnv(iwchan)) then
     722                 :             : 
     723         [ +  + ]:          25 :          if (ngrids==1) then
     724                 :           5 :            write(msg,'(a,i5,a)') ' gij with channel width=  ',iwchan,':'
     725                 :             :          else
     726                 :          20 :            write(msg,'(a,i5,a)') ' gij with channel width=  ',iwchan,' newly converged'
     727                 :             :          end if
     728                 :          25 :          call wrtout(iout,msg,'COLL')
     729                 :             : 
     730                 :          25 :          write(msg,'(a,2i3,3i6,f10.5)')'iatom,iwchan,igqpt2(i),gij error= ',&
     731                 :          50 : &         iatom,iwchan,igqpt2(1),igqpt2(2),igqpt2(3),gijerr+tol10
     732                 :          25 :          call wrtout(iout,msg,'COLL')
     733                 :             : 
     734         [ +  + ]:         275 :          do itemper=1,ntemper
     735                 :             : 
     736                 :             : !          Put zeroes for Bij(k)
     737         [ +  + ]:        1450 :            do iatom=1,natom
     738         [ +  + ]:        8650 :              do ij=1,6
     739                 :        7200 :                bbij(ij,iatom,itemper)=0._dp
     740                 :        8400 :                vij(ij,iatom,itemper)=0._dp
     741                 :             :              end do
     742                 :             :            end do
     743                 :             : 
     744                 :         250 :            tmp=anaddb_dtset%tempermin+anaddb_dtset%temperinc*dble(itemper-1)
     745                 :             : !          tmp in K
     746         [ +  - ]:         250 :            if (tmp < tol6) cycle
     747                 :             : 
     748                 :         250 :            dosinc=dble(iwchan)
     749                 :             : !
     750         [ +  + ]:      109375 :            do ichan=1,nchan2(iwchan)
     751                 :             : !
     752                 :             : !$wovert= \hbar*w / 2kT$, dimensionless
     753                 :      109100 :              wovert=dosinc*(dble(ichan)-half)/Ha_cmm1/(two*kb_HaK*tmp)
     754                 :      109100 :              expm2x=exp(-two*wovert)
     755         [ +  + ]:      727250 :              do iatom=1,natom
     756                 :             : !   factor contains 1 / (2 omega)
     757                 :             :                factor=Ha_cmm1/(two*dosinc*(dble(ichan)-half))    &
     758                 :      617900 : &               *(one+expm2x)/(one-expm2x) /amu(Crystal%typat(iatom))/amu_emass
     759                 :             : 
     760                 :             : !   this becomes * 0.5 * omega for the velocities
     761                 :             :                factorv=(half*dosinc*(dble(ichan)-half)/Ha_cmm1)    &
     762                 :      617900 : &               *(one+expm2x)/(one-expm2x) /amu(Crystal%typat(iatom))/amu_emass
     763                 :             : 
     764         [ +  + ]:     4434400 :                do ij=1,6
     765                 :     3707400 :                  bbij(ij,iatom,itemper)=bbij(ij,iatom,itemper) + factor*gij(ij,iatom,ichan,iwchan)
     766                 :     4325300 :                  vij(ij,iatom,itemper)=vij(ij,iatom,itemper) + factorv*gij(ij,iatom,ichan,iwchan)
     767                 :             :                end do
     768                 :             :              end do
     769                 :             : 
     770                 :             :            end do
     771                 :             : 
     772                 :             :          end do
     773                 :             : 
     774                 :             : !        B matrix is now in atomic unit in the Cartesian coordinates.
     775                 :             : !        Check if Bij(k) changed within tolerance.
     776                 :          25 :          convth=1
     777         [ +  + ]:          25 :          if (ngrids>1) then
     778         [ +  + ]:         112 :            do itemper=1,ntemper
     779         [ +  + ]:         309 :              do iatom=1,natom
     780         [ +  + ]:        1467 :                do ij=1,6
     781                 :        1261 :                  diffbb=bbij(ij,iatom,itemper)-bij(ij,iatom,itemper)
     782                 :             :                  !if (diffbb > 1d-10  .and. diffbb/bij(ij,iatom,itemper) > thmtol) then
     783                 :             :                  !  write(msg,'(a)' )' harmonic_thermo : Bij changes are larger than thmtol '
     784                 :             :                  !  call wrtout(std_out,msg,'COLL')
     785                 :             :                  !  convth=0
     786                 :             :                  !end if
     787         [ +  + ]:        1261 :                  if (diffbb > 1d-10) then
     788         [ +  - ]:         409 :                    if (bij(ij,iatom,itemper) /= zero) then
     789         [ +  + ]:         409 :                      if (diffbb/bij(ij,iatom,itemper) > thmtol) then
     790                 :          11 :                        write(msg,'(a)' )' harmonic_thermo : Bij changes are larger than thmtol '
     791                 :          11 :                        call wrtout(std_out,msg,'COLL')
     792                 :             :                        convth=0
     793                 :             :                      end if
     794                 :             :                    end if
     795                 :             :                  end if
     796                 :         206 :                  if(convth==0)exit
     797                 :             :                end do
     798         [ +  + ]:         309 :                if(convth==0)exit
     799                 :             :              end do
     800         [ +  + ]:         112 :              if(convth==0)exit
     801                 :             :            end do
     802                 :             :          end if
     803                 :             : 
     804   [ -  +  +  +  :        8700 :          bij=bbij ! save for next iteration
             +  +  +  + ]
     805                 :             : 
     806                 :             :          !Update Bij(k) and write them. B matrix printed in angstrom^2
     807                 :             :          !TODO : get rid of this version in the log and output file. Prefer
     808                 :             :          !external files
     809         [ +  + ]:          25 :          if (convth==1) then
     810                 :             :            write(msg, '(a,a,a)' )&
     811                 :          14 : &           ' B matrix elements as a function of T',ch10,&
     812                 :          28 : &           '    Angstrom^2, cartesian coordinates'
     813                 :          14 :            call wrtout(std_out,msg,'COLL')
     814                 :          14 :            call wrtout(iout,msg,'COLL')
     815                 :             : 
     816         [ +  + ]:         154 :            do itemper=1,ntemper
     817                 :             : !            tmp in K
     818                 :         140 :              tmp=anaddb_dtset%tempermin+anaddb_dtset%temperinc*dble(itemper-1)
     819         [ +  + ]:         784 :              do iatom=1,natom
     820                 :             :                write(iout,'(2i3,es11.3,6es12.4)')&
     821                 :         630 : &               iwchan,iatom,tmp+tol10,&
     822                 :         630 : &               Bohr_Ang**2*bij(1,iatom,itemper)+tol10,&
     823                 :         630 : &               Bohr_Ang**2*bij(2,iatom,itemper)+tol10,&
     824                 :         630 : &               Bohr_Ang**2*bij(3,iatom,itemper)+tol10,&
     825                 :         630 : &               Bohr_Ang**2*bij(4,iatom,itemper)+tol10,&
     826                 :         630 : &               Bohr_Ang**2*bij(5,iatom,itemper)+tol10,&
     827                 :        1400 : &               Bohr_Ang**2*bij(6,iatom,itemper)+tol10
     828                 :             :              end do ! end loop over natom
     829                 :             :            end do ! end loop over ntemper
     830                 :             : 
     831                 :             : !        Mean square velocity matrix printed in angstrom^2/picosec^2
     832                 :             :            write(msg, '(a,a,a)' )&
     833                 :          14 : &           ' <vel^2> matrix elements as a function of T',ch10,&
     834                 :          28 : &           '    Angstrom^2/(picosec)^2, cartesian coordinates'
     835                 :          14 :            call wrtout(std_out,msg,'COLL')
     836                 :          14 :            call wrtout(iout,msg,'COLL')
     837                 :             : 
     838         [ +  + ]:         154 :            do itemper=1,ntemper
     839                 :             : !            tmp in K
     840                 :         140 :              tmp=anaddb_dtset%tempermin+anaddb_dtset%temperinc*float(itemper-1)
     841         [ +  + ]:         784 :              do iatom=1,natom
     842         [ +  + ]:        4410 :                vij(:,iatom,itemper)=Bohr_Ang**2*vij(:,iatom,itemper)/(Time_Sec*1.0e12)**2
     843                 :             : !              The following check zeros out <v^2> if it is very small, in order to
     844                 :             : !              avoid numerical noise being interpreted by the automatic tests as
     845                 :             : !              something real. Note also that we compare it in
     846                 :             : !              absolute value, that's because if any of the phonon frequencies are
     847                 :             : !              computed as negative, <v^2> can take a negative value.
     848         [ +  + ]:        4410 :                do icomp=1, 6
     849         [ +  + ]:        4410 :                  if (abs(vij(icomp,iatom,itemper)) < 1.0e-12) vij(icomp,iatom,itemper)=zero
     850                 :             :                end do
     851                 :             :                write(iout,'(2i3,es11.3,6es12.4)')&
     852                 :         630 : &               iwchan,iatom,tmp+tol10,&
     853                 :         630 : &               vij(1,iatom,itemper),&
     854                 :         630 : &               vij(2,iatom,itemper),&
     855                 :         630 : &               vij(3,iatom,itemper),&
     856                 :         630 : &               vij(4,iatom,itemper),&
     857                 :         630 : &               vij(5,iatom,itemper),&
     858                 :        1400 : &               vij(6,iatom,itemper)
     859                 :             :              end do ! end loop over natom
     860                 :             :            end do ! end loop over ntemper
     861                 :             :          end if ! end check on convergence
     862                 :             : 
     863                 :             : 
     864                 :             :          ! keep this one !!!!!!!!!!!!!!!!!!
     865                 :             :          if (convth==1) then
     866                 :             :            write(msg, '(a,a,a)' )&
     867                 :          14 : &           '# B matrix elements as a function of T, for each atom, and smallest omega channel width',ch10,&
     868                 :          28 : &           '#    Angstrom^2, cartesian coordinates'
     869                 :          14 :            call wrtout(bij_unit,msg,'COLL')
     870         [ +  + ]:          77 :            do iatom=1,natom
     871                 :          63 :              write(msg, '(2a,i10)' ) ch10, '# for atom ', iatom
     872                 :          63 :              call wrtout(bij_unit,msg,'COLL')
     873         [ +  + ]:         707 :              do itemper=1,ntemper
     874                 :             : !              tmp in K
     875                 :         630 :                tmp=anaddb_dtset%tempermin+anaddb_dtset%temperinc*dble(itemper-1)
     876                 :             :                write(msg,'(es11.3,6es12.4)')&
     877                 :         630 : &               tmp,&
     878                 :         630 : &               Bohr_Ang**2*bij(1,iatom,itemper),&
     879                 :         630 : &               Bohr_Ang**2*bij(2,iatom,itemper),&
     880                 :         630 : &               Bohr_Ang**2*bij(3,iatom,itemper),&
     881                 :         630 : &               Bohr_Ang**2*bij(4,iatom,itemper),&
     882                 :         630 : &               Bohr_Ang**2*bij(5,iatom,itemper),&
     883                 :        1260 : &               Bohr_Ang**2*bij(6,iatom,itemper)
     884                 :         693 :                call wrtout(bij_unit,msg,'COLL')
     885                 :             :              end do ! end loop over ntemper
     886                 :             :            end do ! end loop over natom
     887                 :             : 
     888                 :             : !        Mean square velocity matrix printed in angstrom^2/picosec^2
     889                 :             :            write(msg, '(a,a,a)' )&
     890                 :          14 : &           '# <vel^2> matrix elements as a function of T, for each atom, and smallest channel width',ch10,&
     891                 :          28 : &           '#    Angstrom^2/(picosec)^2, cartesian coordinates'
     892                 :          14 :            call wrtout(vij_unit,msg,'COLL')
     893                 :             : 
     894         [ +  + ]:          77 :            do iatom=1,natom
     895                 :          63 :              write(msg, '(2a,i10)' ) ch10, '# for atom ', iatom
     896                 :          63 :              call wrtout(vij_unit,msg,'COLL')
     897         [ +  + ]:         707 :              do itemper=1,ntemper
     898                 :             : !            tmp in K
     899                 :         630 :                tmp=anaddb_dtset%tempermin+anaddb_dtset%temperinc*float(itemper-1)
     900         [ +  + ]:        4410 :                vij(:,iatom,itemper)=Bohr_Ang**2*vij(:,iatom,itemper)/(Time_Sec*1.0e12)**2
     901                 :             : 
     902                 :             : !            The following check zeros out <v^2> if it is very small, in order to
     903                 :             : !            avoid numerical noise being interpreted by the automatic tests as
     904                 :             : !            something real. Note also that we compare it in
     905                 :             : !            absolute value, that's because if any of the phonon frequencies are
     906                 :             : !            computed as negative, <v^2> can take a negative value.
     907         [ +  + ]:        4410 :                do icomp=1, 6
     908         [ +  + ]:        4410 :                  if (abs(vij(icomp,iatom,itemper)) < 1.0e-12) vij(icomp,iatom,itemper)=zero
     909                 :             :                end do
     910                 :             :                write(vij_unit,'(es11.3,6es12.4)')&
     911                 :         630 : &               tmp,&
     912                 :         630 : &               vij(1,iatom,itemper),&
     913                 :         630 : &               vij(2,iatom,itemper),&
     914                 :         630 : &               vij(3,iatom,itemper),&
     915                 :         630 : &               vij(4,iatom,itemper),&
     916                 :         630 : &               vij(5,iatom,itemper),&
     917                 :        1323 : &               vij(6,iatom,itemper)
     918                 :             :              end do ! end loop over ntemper
     919                 :             :            end do ! end loop over natom
     920                 :             :          end if ! end check on convergence
     921                 :             : 
     922                 :             :          if(convth==1)part2=.true.
     923                 :             : 
     924                 :             :        end if ! End of test on wgijcnv
     925                 :             :      end do ! End of loop over iwchan
     926                 :             :    end if ! End of part2
     927                 :             : 
     928         [ +  + ]:          14 :    if(part1.and.part2)exit
     929                 :             : 
     930         [ -  + ]:          12 :    ABI_FREE(indqpt1)
     931         [ -  + ]:          12 :    ABI_FREE(qpt2)
     932         [ -  + ]:          12 :    ABI_FREE(spqpt2)
     933         [ -  + ]:          12 :    ABI_FREE(wtq)
     934         [ -  + ]:          16 :    ABI_FREE(wtq2)
     935                 :             : 
     936                 :             :  end do ! End of the Loop on the q point grids
     937                 :             : 
     938         [ -  + ]:           4 :  ABI_FREE(bbij)
     939         [ -  + ]:           4 :  ABI_FREE(bij)
     940         [ -  + ]:           4 :  ABI_FREE(energy)
     941         [ -  + ]:           4 :  ABI_FREE(energy0)
     942         [ -  + ]:           4 :  ABI_FREE(entropy)
     943         [ -  + ]:           4 :  ABI_FREE(entropy0)
     944         [ -  + ]:           4 :  ABI_FREE(free)
     945         [ -  + ]:           4 :  ABI_FREE(free0)
     946         [ -  + ]:           4 :  ABI_FREE(gdos)
     947         [ -  + ]:           4 :  ABI_FREE(gg)
     948         [ -  + ]:           4 :  ABI_FREE(gg_sum)
     949         [ -  + ]:           4 :  ABI_FREE(gg_rest)
     950         [ -  + ]:           4 :  ABI_FREE(ggij)
     951         [ -  + ]:           4 :  ABI_FREE(gij)
     952         [ -  + ]:           4 :  ABI_FREE(nchan2)
     953         [ -  + ]:           4 :  ABI_FREE(spheat)
     954         [ -  + ]:           4 :  ABI_FREE(spheat0)
     955         [ -  + ]:           4 :  ABI_FREE(vij)
     956         [ -  + ]:           4 :  ABI_FREE(wgcnv)
     957         [ -  + ]:           4 :  ABI_FREE(wgijcnv)
     958         [ +  + ]:           4 :  if(allocated(indqpt1)) then
     959                 :           2 :    ABI_FREE(indqpt1)
     960                 :             :  end if
     961         [ +  + ]:           4 :  if(allocated(qpt2)) then
     962                 :           2 :    ABI_FREE(qpt2)
     963                 :             :  end if
     964         [ +  + ]:           4 :  if(allocated(spqpt2)) then
     965                 :           2 :    ABI_FREE(spqpt2)
     966                 :             :  end if
     967         [ +  + ]:           4 :  if(allocated(wtq)) then
     968                 :           2 :    ABI_FREE(wtq)
     969                 :             :  end if
     970         [ +  + ]:           4 :  if(allocated(wtq2)) then
     971                 :           2 :    ABI_FREE(wtq2)
     972                 :             :  end if
     973         [ -  + ]:           4 :  ABI_FREE(gw)
     974         [ -  + ]:           4 :  ABI_FREE(wme)
     975                 :             : 
     976         [ -  + ]:           4 :  if(.not.part1)then
     977                 :             :    write(msg, '(a,a,a,a,a,a,a,a,a)' )&
     978                 :           0 : &   'No thermodynamical function is printed out :',ch10,&
     979                 :           0 : &   'the tolerance level that was asked ',ch10,&
     980                 :           0 : &   'has not been match with the grids specified.',ch10,&
     981                 :           0 : &   'Action: in the input file, increase the resolution',ch10,&
     982                 :           0 : &   'of grids ng2qpt, or decrease the accuracy requirement thmtol.'
     983                 :           0 :    ABI_ERROR(msg)
     984                 :             :  end if
     985                 :             : 
     986         [ +  + ]:           4 :  if(.not.part2)then
     987                 :             :    write(msg,'(a,a,a,a,a,a,a,a,a)')&
     988                 :           2 : &   'No atomic factor tensor is printed out :',ch10,&
     989                 :           2 : &   'the tolerance level that was asked ',ch10,&
     990                 :           2 : &   'has not been match with the grids specified.',ch10,&
     991                 :           2 : &   'Action: in the input file, increase the resolution',ch10,&
     992                 :           4 : &   'of grids ng2qpt, or decrease the accuracy requirement thmtol.'
     993                 :           2 :    ABI_WARNING(msg)
     994                 :             :  end if
     995                 :             : 
     996                 :           4 :  close (thermal_unit)
     997                 :           4 :  close (bij_unit)
     998                 :           4 :  close (vij_unit)
     999                 :             : 
    1000                 :             : end subroutine harmonic_thermo
    1001                 :             : !!***
    1002                 :             : 
    1003                 :             : end module m_harmonic_thermo
    1004                 :             : !!***
        

Generated by: LCOV version 2.3-1