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 % 499 474
Test Date: 2026-11-08 00:10:28 Functions: 100.0 % 1 1
Branches: 70.9 % 788 559

             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, qmesh_from_brav_ngqpt, kptrlatt_ncells
      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,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,nqshft_use
     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),q2shft_use(3,1)
     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   [ +  +  +  + ]:          52 :  rprimd = Ifc%rprimd
     142   [ +  +  +  + ]:          52 :  gprimd = Ifc%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                 :             : !Loops on the q point grids
     237         [ +  + ]:          16 :  do igrid=1,ngrids
     238                 :             : 
     239         [ +  + ]:          56 :    igqpt2(:)=max((anaddb_dtset%ng2qpt(:)*igrid)/ngrids, 1)
     240                 :             :    ! Translate the (brav, ngqpt, q2shft) specification into a brav-independent q-mesh lattice.
     241                 :          14 :    option=1
     242                 :          14 :    call qmesh_from_brav_ngqpt(anaddb_dtset%brav, igqpt2, 1, anaddb_dtset%q2shft, qptrlatt, nqshft_use, q2shft_use)
     243                 :          14 :    mqpt2 = kptrlatt_ncells(qptrlatt, nqshft_use)
     244   [ -  +  +  -  :          42 :    ABI_MALLOC(qpt2,(3,mqpt2))
          +  -  +  -  -  
                +  -  + ]
     245   [ -  +  +  -  :          28 :    ABI_MALLOC(spqpt2,(3,mqpt2))
             -  +  -  + ]
     246                 :          14 :    call smpbz(iout,qptrlatt,mqpt2,nspqpt,nqshft_use,option,q2shft_use,spqpt2)
     247                 :             : 
     248   [ -  +  +  -  :          42 :    ABI_MALLOC(indqpt1,(nspqpt))
          +  -  +  -  -  
                +  -  + ]
     249   [ -  +  +  -  :          42 :    ABI_MALLOC(wtq,(nspqpt))
          +  -  +  -  -  
                +  -  + ]
     250   [ -  +  +  -  :          28 :    ABI_MALLOC(wtq_folded,(nspqpt))
             -  +  -  + ]
     251   [ -  +  +  -  :          42 :    ABI_MALLOC(bz2ibz_smap,(6, nspqpt))
          +  -  +  -  -  
                +  -  + ]
     252                 :             : 
     253                 :             : !  Reduce the number of such points by symmetrization
     254         [ +  + ]:       31918 :    wtq(:)=1.0_dp
     255                 :             : 
     256                 :          14 :    timrev=1
     257                 :             :    call symkpt(0,Crystal%gmet,indqpt1,ab_out,spqpt2,nspqpt,nqpt2,Crystal%nsym,symrec,timrev,wtq,wtq_folded, &
     258                 :          14 :      bz2ibz_smap, xmpi_comm_self)
     259                 :             : 
     260         [ -  + ]:          14 :    ABI_FREE(bz2ibz_smap)
     261                 :             : 
     262   [ -  +  +  -  :          42 :    ABI_MALLOC(wtq2,(nqpt2))
          +  -  +  -  -  
                +  -  + ]
     263         [ +  + ]:        1760 :    do iqpt2=1,nqpt2
     264                 :        1746 :      wtq2(iqpt2)=wtq_folded(indqpt1(iqpt2))
     265         [ +  + ]:        6998 :      qpt2(:,iqpt2)=spqpt2(:,indqpt1(iqpt2))
     266                 :             :      !write(std_out,*)' harmonic_thermo : iqpt2, wtq2 :',iqpt2,wtq2(iqpt2)
     267                 :             :    end do
     268         [ -  + ]:          14 :    ABI_FREE(wtq_folded)
     269                 :             : 
     270                 :             : !  Temporary counters are put zero.
     271                 :             : 
     272   [ +  +  +  + ]:      192609 :    gg(:,:)=zero
     273   [ +  +  +  +  :     2668859 :    ggij(:,:,:,:)=zero
             +  +  +  + ]
     274   [ +  +  +  + ]:       96359 :    gw(:,:)=zero
     275                 :             : 
     276                 :             : !  Sum over the sampled q points
     277         [ +  + ]:        1760 :    do iqpt2=1,nqpt2
     278                 :             : 
     279         [ +  + ]:        6984 :      qphon(:)=qpt2(:,iqpt2)
     280                 :        1746 :      qphnrm=1.0_dp
     281                 :             : 
     282                 :             :      ! Fourier Interpolation
     283                 :        1746 :      call ifc%fourq(Crystal,qphon,phfrq,displ,out_eigvec=eigvec)
     284                 :             : 
     285         [ -  + ]:        1746 :      if (present(thmflag)) then
     286         [ #  # ]:           0 :        if (thmflag ==2)then
     287                 :           0 :          call sortph(eigvec,displ,outfilename_radix,natom,phfrq)
     288                 :             :        end if
     289                 :             :      end if
     290                 :             : 
     291                 :             : !    Sum over the phonon modes
     292         [ +  + ]:       33782 :      do iii=1,3*natom
     293                 :             : 
     294                 :             : !      Slightly negative frequencies are put to zero
     295                 :             : !      Imaginary frequencies are also put to zero
     296         [ +  + ]:       32022 :        if(phfrq(iii)<0._dp) phfrq(iii)=0._dp
     297                 :             : 
     298                 :             : !      Note: frequencies are now in cm-1
     299                 :             : 
     300                 :             : !      Sort frequencies into channels of frequencies for each channel width of frequency
     301         [ +  + ]:      198432 :        do iwchan=nwchan,1,-1
     302         [ +  + ]:      198432 :          if (.not.wgcnv(iwchan))then
     303                 :      164874 :            dosinc=dble(iwchan)
     304                 :      164874 :            ichan=int(phfrq(iii)*Ha_cmm1/dosinc)+1
     305                 :             : 
     306         [ -  + ]:      164874 :            if(ichan>nchan2(iwchan)) then
     307                 :             :              write(msg, '(a,es16.6,a,a,a,i7,a,a,a)' )&
     308                 :           0 : &             'There is a phonon frequency,',phfrq(iii),' larger than the maximum one,',ch10,&
     309                 :           0 : &             'as defined by the number of channels of width 1 cm-1, nchan=',nchan,'.',ch10,&
     310                 :           0 : &             'Action: increase nchan (suggestion : double it).'
     311                 :           0 :              ABI_ERROR(msg)
     312                 :             :            end if
     313                 :             : 
     314                 :      164874 :            gg(ichan,iwchan)=gg(ichan,iwchan)+wtq2(iqpt2)
     315                 :             : 
     316                 :      164874 :            gw(ichan,iwchan)=gw(ichan,iwchan)+wtq2(iqpt2)*phfrq(iii)*Ha_cmm1
     317                 :             : 
     318                 :             : !          to calculate two phonon DOS for qshift = 0.0
     319         [ +  + ]:     4062828 :            do iiii=1,3*natom
     320         [ -  + ]:     3897954 :              if(phfrq(iiii)<0.d0) phfrq(iiii)=0.d0
     321                 :             : 
     322                 :     3897954 :              ichan=int(abs(phfrq(iii)+phfrq(iiii))*Ha_cmm1/dosinc)+1
     323                 :     3897954 :              gg_sum(ichan,iwchan)=gg_sum(ichan,iwchan)+wtq2(iqpt2)
     324                 :             : 
     325                 :     3897954 :              ichan=int(abs(phfrq(iii)-phfrq(iiii))*Ha_cmm1/dosinc)+1
     326                 :     4062828 :              gg_rest(ichan,iwchan)=gg_rest(ichan,iwchan)+wtq2(iqpt2)
     327                 :             :            end do ! end loop for iiii
     328                 :             : 
     329                 :             :          end if
     330                 :             :        end do
     331                 :             : 
     332         [ +  + ]:      200178 :        do iwchan=nwchan,1,-1
     333         [ +  + ]:      198432 :          if (.not.wgijcnv(iwchan))then
     334                 :             : 
     335                 :      105660 :            dosinc=dble(iwchan)
     336                 :      105660 :            ichan=int(phfrq(iii)*Ha_cmm1/dosinc)+1
     337                 :             : 
     338         [ -  + ]:      105660 :            if(ichan>nchan2(iwchan)) then
     339                 :             :              write(msg, '(a,a,a,a,a)' )&
     340                 :           0 : &             'Phonon frequencies larger than the maximum one,',ch10,&
     341                 :           0 : &             'as defined by the number of channels of width 1 cm-1.',ch10,&
     342                 :           0 : &             'Action: increase nchan (suggestion : double it).'
     343                 :           0 :              ABI_ERROR(msg)
     344                 :             :            end if
     345                 :             : 
     346         [ +  + ]:     1054080 :            do iatom=1,natom
     347         [ +  + ]:     6744600 :              do ij=1,6
     348                 :             :                ggij(ij,iatom,ichan,iwchan)=ggij(ij,iatom,ichan,iwchan)&
     349                 :             : &               +wtq2(iqpt2)*&
     350                 :             : &               (eigvec(1,ii(ij),iatom,iii)*eigvec(1,jj(ij),iatom,iii)+&
     351                 :     6638940 : &               eigvec(2,ii(ij),iatom,iii)*eigvec(2,jj(ij),iatom,iii) )
     352                 :             :              end do
     353                 :             :            end do
     354                 :             : 
     355                 :             :          end if
     356                 :             :        end do
     357                 :             : 
     358                 :             :      end do ! End of the sum over the phonon modes
     359                 :             :    end do ! End of the sum over q-points in the irreducible zone
     360                 :             : 
     361                 :             : !  deallocate sortph array
     362                 :          14 :    call end_sortph()
     363                 :             : 
     364                 :             : !  Symmetrize the gij
     365         [ +  + ]:       15264 :    do ichan=1,nchan
     366         [ +  + ]:      111514 :      do iwchan=nwchan,1,-1
     367         [ +  + ]:      463750 :        do iatom=1,natom
     368         [ +  + ]:     2668750 :          do ij=1,6
     369                 :             : !          Uses bbij as work space
     370                 :     2205000 :            bbij(ij,iatom,1)=ggij(ij,iatom,ichan,iwchan)
     371                 :     2572500 :            ggij(ij,iatom,ichan,iwchan)=0.0_dp
     372                 :             :          end do
     373                 :             :        end do
     374         [ +  + ]:      479000 :        do iatom=1,natom
     375         [ +  + ]:     5137500 :          do isym=1,Crystal%nsym
     376                 :             : !          Find the atom that will be applied on atom iatom
     377                 :     4770000 :            ind=Crystal%indsym(4,isym,iatom)
     378         [ +  + ]:    33390000 :            do ij=1,6
     379                 :    33390000 :              tens1(ii(ij),jj(ij))=bbij(ij,ind,1)
     380                 :             :            end do
     381                 :             : !          complete the 3x3 tensor from the upper triangle
     382                 :     4770000 :            tens1(2,1)=tens1(1,2)
     383                 :     4770000 :            tens1(3,1)=tens1(1,3)
     384                 :     4770000 :            tens1(3,2)=tens1(2,3)
     385                 :             : !          Here acomplishes the tensorial operations
     386                 :             : !!          make this a BLAS call, or better yet batch the whole thing?
     387                 :             : !          2) Apply the symmetry operation on both indices   USING symrec in
     388                 :             : !          cartesian coordinates
     389         [ +  + ]:    19080000 :            do iii=1,3
     390         [ +  + ]:    62010000 :              do jjj=1,3
     391                 :             :                tens2(iii,jjj)=tens1(iii,1)*symrec_cart(1,jjj,isym)&
     392                 :             : &               +tens1(iii,2)*symrec_cart(2,jjj,isym)&
     393                 :    57240000 : &               +tens1(iii,3)*symrec_cart(3,jjj,isym)
     394                 :             :              end do
     395                 :             :            end do
     396         [ +  + ]:    19080000 :            do jjj=1,3
     397         [ +  + ]:    62010000 :              do iii=1,3
     398                 :             :                tens1(iii,jjj)=tens2(1,jjj)*symrec_cart(1,iii,isym)&
     399                 :             : &               +tens2(2,jjj)*symrec_cart(2,iii,isym)&
     400                 :    57240000 : &               +tens2(3,jjj)*symrec_cart(3,iii,isym)
     401                 :             :              end do
     402                 :             :            end do
     403                 :             : ! net result is tens1 = rprimd symrec^T gprimd^T   tens1   gprimd symrec rprimd^T
     404                 :             : 
     405                 :             : !          This accumulates over atoms, to account for all symmetric ones
     406         [ +  + ]:    33757500 :            do ij=1,6
     407                 :    33390000 :              ggij(ij,iatom,ichan,iwchan)=ggij(ij,iatom,ichan,iwchan) + tens1(ii(ij),jj(ij))
     408                 :             :            end do
     409                 :             : 
     410                 :             :          end do
     411                 :             : !        Each one will be replicated nsym times in the end:
     412         [ +  + ]:     2668750 :          do ij=1,6
     413                 :     2572500 :            ggij(ij,iatom,ichan,iwchan)=ggij(ij,iatom,ichan,iwchan)/dble(Crystal%nsym)
     414                 :             :          end do
     415                 :             :        end do
     416                 :             :      end do
     417                 :             :    end do
     418                 :             : 
     419                 :          14 :    call wrtout(std_out,' harmonic_thermo: g(w) and gij(k|w) calculated given a q sampling grid.','COLL')
     420                 :             : 
     421                 :             : !  Sum up the counts in the channels to check the normalization
     422                 :             : !  and test convergence with respect to q sampling
     423                 :          14 :    gnorm=nspqpt*3*natom
     424                 :             : 
     425         [ +  - ]:          14 :    if(.not.part1)then
     426         [ +  + ]:          87 :      do iwchan=nwchan,1,-1
     427                 :             : 
     428                 :             :        !write(msg,'(a,i0)' )' harmonic_thermo : iwchan=',iwchan
     429                 :             :        !call wrtout(std_out,msg,'COLL')
     430                 :             : 
     431         [ +  + ]:          77 :        if (wgcnv(iwchan)) cycle
     432                 :             :        !call wrtout(std_out,' harmonic_thermo : compute g, f, e, s, c','COLL')
     433                 :             : 
     434                 :             : !      Calculate g(w) and F,E,S,C
     435                 :             : 
     436                 :          76 :        ggsum=0.0_dp
     437                 :          76 :        ggsumsum=0.0_dp
     438                 :          76 :        ggrestsum=0.0_dp
     439         [ +  + ]:       27881 :        do ichan=1,nchan2(iwchan)
     440                 :       27805 :          ggsum=ggsum+gg(ichan,iwchan)
     441                 :       27805 :          ggsumsum=ggsumsum+gg_sum(ichan,iwchan)
     442                 :       27881 :          ggrestsum=ggrestsum+gg_rest(ichan,iwchan)
     443                 :             :        end do
     444                 :             : 
     445         [ -  + ]:          76 :        if(ggsum/=gnorm)then
     446                 :             :          write(msg, '(a,es14.6,i6,a,a,es14.6,a)' )&
     447                 :           0 : &         'Frequencies are missing in g(w) : ggsum,iwchan=',ggsum,iwchan,ch10,&
     448                 :           0 : &         'gnorm=',gnorm,'.'
     449                 :           0 :          ABI_BUG(msg)
     450                 :             :        end if
     451                 :             : 
     452                 :             : !      Check if the density of states changed by more than dostol
     453                 :             : 
     454                 :          76 :        gerr=zero
     455         [ +  + ]:          76 :        if (ngrids>1) then
     456         [ +  + ]:       27630 :          do ichan=1,nchan2(iwchan)
     457                 :       27630 :            gerr=gerr+abs(gg(ichan,iwchan)/ggsum-gdos(ichan,iwchan))
     458                 :             :          end do
     459                 :             :        end if
     460                 :             : 
     461   [ +  +  +  - ]:          76 :        if(gerr>anaddb_dtset%dostol.and.ngrids>1) then
     462                 :          69 :          wgcnv(iwchan)=.false.
     463                 :             :        else
     464                 :           7 :          wgcnv(iwchan)=.true.
     465                 :             :        end if
     466                 :             : 
     467                 :             : !      g(w) is updated
     468         [ +  + ]:       27881 :        do ichan=1,nchan2(iwchan)
     469                 :       27805 :          gdos(ichan,iwchan)=gg(ichan,iwchan)/ggsum
     470                 :       27805 :          gg_sum(ichan,iwchan)=gg_sum(ichan,iwchan)/ggsumsum
     471                 :       27881 :          gg_rest(ichan,iwchan)=gg_rest(ichan,iwchan)/ggrestsum
     472                 :             :        end do
     473         [ +  + ]:       27881 :        do ichan=1,nchan2(iwchan)
     474                 :       27881 :          gw(ichan,iwchan)=gw(ichan,iwchan)/ggsum
     475                 :             :        end do
     476                 :             : 
     477                 :             : !      Write gerr for each q sampling and w width
     478                 :          76 :        write(msg,'(a,a,i3,3i6,f10.1,f10.5)') ch10, &
     479                 :         152 : &       'harmonic_thermo: iwchan,igqpt(:),norm,error=',iwchan,igqpt2(1),igqpt2(2),igqpt2(3),ggsum+tol8,gerr+tol10
     480                 :          76 :        call wrtout(std_out,msg,'COLL')
     481                 :             : 
     482                 :             : !      If the DOS with a channel width is newly converged,
     483                 :             : !      print it out and calculate the thermodynamic functions.
     484                 :          76 :        convth=0
     485         [ +  + ]:          76 :        if(wgcnv(iwchan)) then
     486         [ +  + ]:           7 :          if (ngrids==1) then
     487         [ -  + ]:           1 :            if (anaddb_dtset%dossum /= 0 ) then
     488                 :           0 :              write(msg,'(a65,i5,a16)') ' DOS, SUM AND DIFFERENCE OF TWO PHONON DOS with channel width= ',iwchan,':'
     489                 :             :            else
     490                 :           1 :              write(msg,'(a25,i5,a16)') ' DOS  with channel width=  ',iwchan,':'
     491                 :             :            end if
     492                 :             :          else
     493         [ +  + ]:           6 :            if (anaddb_dtset%dossum /= 0 ) then
     494                 :             :              write(msg,'(a65,i5,a16)')&
     495                 :           2 : &             ' DOS, SUM AND DIFFERENCE OF TWO PHONON DOS  with channel width= ',iwchan,' newly converged'
     496                 :             :            else
     497                 :           4 :              write(msg,'(a25,i5,a16)') ' DOS  with channel width=  ',iwchan,' newly converged'
     498                 :             :            end if
     499                 :             :          end if
     500                 :             : 
     501                 :           7 :          call wrtout(std_out,msg,'COLL')
     502                 :           7 :          call wrtout(iout,msg,'COLL')
     503         [ +  + ]:        1552 :          do ichan=1,nchan2(iwchan)
     504         [ +  + ]:        1545 :            if (anaddb_dtset%dossum /= 0 ) then
     505                 :         563 :              write(msg,'(i8,f11.1,3(f12.5,3x))') ichan,gg(ichan,iwchan)+tol10,&
     506                 :         563 : &             gdos(ichan,iwchan)+tol10, gg_sum(ichan,iwchan)*(3.0*natom*3.0*natom)+tol10, &
     507                 :        1126 : &             gg_rest(ichan,iwchan)*(3.0*natom*(3.0*natom-1))+tol10
     508                 :             :            else
     509                 :         982 :              write(msg,'(i8,f11.1,1x,f12.5)') ichan,gg(ichan,iwchan)+tol10,&
     510                 :        1964 : &             gdos(ichan,iwchan)+tol10
     511                 :             :            end if
     512                 :        1552 :            call wrtout(std_out,msg,'COLL')
     513                 :             :          end do
     514                 :             : 
     515         [ +  + ]:           7 :          if (ngrids>1) then
     516                 :           6 :            write(msg,'(a24,f10.5)')'   with maximal error = ',gerr+tol10
     517                 :           6 :            call wrtout(std_out,msg,'COLL')
     518                 :           6 :            call wrtout(iout,msg,'COLL')
     519                 :             :          end if
     520                 :             : 
     521                 :           7 :          nomega = nchan2(iwchan)
     522                 :           7 :          dosinc=dble(iwchan)
     523                 :             : 
     524   [ -  +  +  -  :          21 :          ABI_MALLOC(phon_dos,(nomega))
          +  -  +  -  -  
                +  -  + ]
     525   [ -  +  +  + ]:        1559 :          phon_dos = gdos(1:nomega,iwchan)
     526                 :             : 
     527                 :             : !Put zeroes for F, E, S, Cv
     528         [ +  + ]:          77 :          free(:)=zero
     529         [ +  + ]:          77 :          energy(:)=zero
     530         [ +  + ]:          77 :          entropy(:)=zero
     531         [ +  + ]:          77 :          spheat(:)=zero
     532         [ +  + ]:          77 :          wme(:)=zero
     533                 :             : 
     534         [ +  + ]:          77 :          do itemper=1,ntemper
     535                 :             : 
     536                 :          70 :            tmp=anaddb_dtset%tempermin+anaddb_dtset%temperinc*dble(itemper-1)
     537                 :             : !          The temperature (tmp) is given in Kelvin
     538         [ +  - ]:          70 :            if (tmp < tol6) cycle
     539                 :             : 
     540         [ +  + ]:       15520 :            do iomega=1,nomega
     541                 :             : 
     542                 :             : !            wovert= hbar*w / 2kT dimensionless
     543                 :       15450 :              wovert=dosinc*(dble(iomega)-0.5_dp)/Ha_cmm1/(2._dp*kb_HaK*tmp)
     544                 :       15450 :              expm2x=exp(-2.0_dp*wovert)
     545                 :       15450 :              ln2shx=wovert+log(1.0_dp-expm2x)
     546                 :       15450 :              cothx=(1.0_dp+expm2x)/(1.0_dp-expm2x)
     547                 :       15450 :              factor=dble(3*natom)*phon_dos(iomega)
     548                 :       15450 :              factorw=3*natom*gw(iomega,iwchan)
     549                 :             : 
     550                 :             : !            This matches the equations published in Lee & Gonze, PRB 51, 8610 (1995) [[cite:Lee1995]]
     551                 :       15450 :              free(itemper)=free(itemper) +factor*kb_HaK*tmp*ln2shx
     552                 :       15450 :              energy(itemper)=energy(itemper) + factor*kb_HaK*tmp*wovert*cothx
     553                 :       15450 :              entropy(itemper)=entropy(itemper) + factor*kb_HaK*(wovert*cothx - ln2shx)
     554                 :             : 
     555                 :             : !            The contribution is much lower than 1.0d-16 when wovert<100.0_dp
     556         [ +  - ]:       15450 :              if(wovert<100.0_dp)then
     557                 :       15450 :                spheat(itemper)=spheat(itemper)+factor*kb_HaK*wovert**2/sinh(wovert)**2
     558                 :             :              end if
     559                 :       15520 :              wme(itemper)=wme(itemper)+factorw*kb_HaK*wovert**2/sinh(wovert)**2
     560                 :             : 
     561                 :             :            end do ! iomega
     562                 :             : 
     563         [ +  - ]:          77 :            if (abs(spheat(itemper))>tol8) wme(itemper)=wme(itemper)/spheat(itemper)
     564                 :             :          end do ! itemper
     565         [ -  + ]:           7 :          ABI_FREE(phon_dos)
     566                 :             : 
     567                 :             : !        Check if the thermodynamic functions change within tolerance,
     568         [ +  + ]:           7 :          if (ngrids>1) then
     569                 :             :            write(msg,'(a,a,a)')&
     570                 :           6 : &           ' harmonic_thermo : check if the thermodynamic functions',ch10,&
     571                 :          12 : &           '    change within tolerance.'
     572                 :           6 :            call wrtout(std_out,msg,'COLL')
     573                 :           6 :            convth=1
     574                 :             : 
     575         [ +  + ]:          36 :            do itemper=1,ntemper
     576                 :          33 :              change=free(itemper)-free0(itemper)
     577                 :          33 :              relchg=change/free0(itemper)
     578   [ +  -  +  + ]:          33 :              if(change>1d-14*dble(mqpt2) .and. relchg>thmtol)then
     579                 :             :                write(msg,'(a,es14.4,a,a,es14.4)' )&
     580                 :           3 : &               ' harmonic_thermo : free energy relative changes ',relchg,ch10,&
     581                 :           6 : &               '        are larger than thmtol ',thmtol
     582                 :           3 :                call wrtout(std_out,msg,'COLL')
     583                 :           3 :                convth=0
     584                 :             :              end if
     585                 :          33 :              change=energy(itemper)-energy0(itemper)
     586                 :          33 :              relchg=change/energy0(itemper)
     587   [ +  +  +  + ]:          33 :              if(change>1d-14*dble(mqpt2) .and. relchg>thmtol)then
     588                 :             :                write(msg,'(a,es14.4,a,a,es14.4)' )&
     589                 :           3 : &               ' harmonic_thermo : energy relative changes ',relchg,ch10,&
     590                 :           6 : &               '        are larger than thmtol ',thmtol
     591                 :           3 :                call wrtout(std_out,msg,'COLL')
     592                 :           3 :                convth=0
     593                 :             :              end if
     594                 :          33 :              change=entropy(itemper)-entropy0(itemper)
     595                 :          33 :              relchg=change/entropy0(itemper)
     596   [ +  +  +  - ]:          33 :              if(change>1d-14*dble(mqpt2) .and. relchg>thmtol)then
     597                 :             :                write(msg,'(a,es14.4,a,a,es14.4)' )&
     598                 :           1 : &               ' harmonic_thermo : entropy relative changes ',relchg,ch10,&
     599                 :           2 : &               '        are larger than thmtol ',thmtol
     600                 :           1 :                call wrtout(std_out,msg,'COLL')
     601                 :           1 :                convth=0
     602                 :             :              end if
     603                 :          33 :              change=spheat(itemper)-spheat0(itemper)
     604                 :          33 :              relchg=change/spheat0(itemper)
     605   [ +  +  +  + ]:          33 :              if(change>1d-14*dble(mqpt2) .and. relchg>thmtol)then
     606                 :             :                write(msg,'(a,es14.4,a,a,es14.4)' )&
     607                 :           1 : &               ' harmonic_thermo : specific heat relative changes ',relchg,ch10,&
     608                 :           2 : &               '        are larger than thmtol ',thmtol
     609                 :           1 :                call wrtout(std_out,msg,'COLL')
     610                 :             :                convth=0
     611                 :             :              end if
     612                 :             : 
     613         [ +  + ]:          35 :              if(convth==0)exit
     614                 :             :            end do ! End of check if the thermodynamic functions change within tolerance
     615                 :             : 
     616                 :             :          else
     617                 :             :            convth=1
     618                 :             :          end if
     619                 :             : 
     620                 :             : !        Update F,E,S,C and eventually write them if converged
     621         [ +  + ]:           6 :          if(convth==1)then
     622                 :           4 :            part1=.true.
     623                 :           4 :            write(msg,'(a,a,a)') ch10,&
     624                 :           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)'
     625                 :           4 :            call wrtout(iout,msg,'COLL')
     626                 :           4 :            call wrtout(thermal_unit,msg,'COLL')
     627                 :           4 :            msg = ' # (A mol-c is the abbreviation of a mole-cell, that is, the'
     628                 :           4 :            call wrtout(iout,msg,'COLL')
     629                 :           4 :            call wrtout(thermal_unit,msg,'COLL')
     630                 :           4 :            msg = ' #  number of Avogadro times the atoms in a unit cell)'
     631                 :           4 :            call wrtout(iout,msg,'COLL')
     632                 :           4 :            call wrtout(thermal_unit,msg,'COLL')
     633                 :             : 
     634                 :             :            write(msg, '(a,a,a)' )&
     635                 :           4 : &           ' harmonic_thermo : thermodynamic functions have converged',ch10,&
     636                 :           8 : &           '     see main output file ...'
     637                 :           4 :            call wrtout(std_out,msg,'COLL')
     638                 :             :          end if
     639                 :             : 
     640         [ +  + ]:          77 :          do itemper=1,ntemper
     641                 :          70 :            free0(itemper)=free(itemper)
     642                 :          70 :            energy0(itemper)=energy(itemper)
     643                 :          70 :            entropy0(itemper)=entropy(itemper)
     644                 :          70 :            spheat0(itemper)=spheat(itemper)
     645                 :             : 
     646         [ +  + ]:          77 :            if(convth==1)then
     647                 :          40 :              tmp=anaddb_dtset%tempermin+anaddb_dtset%temperinc*dble(itemper-1)
     648                 :          40 :              write(msg,'(es11.3,5es15.7)') tmp+tol8,&
     649                 :          40 : &             Ha_eV*e_Cb*Avogadro*free(itemper),&
     650                 :          40 : &             Ha_eV*e_Cb*Avogadro*energy(itemper),&
     651                 :          40 : &             Ha_eV*e_Cb*Avogadro*entropy(itemper),&
     652                 :          40 : &             Ha_eV*e_Cb*Avogadro*spheat(itemper),&
     653                 :          80 : &             wme(itemper)
     654                 :          40 :              call wrtout(iout,msg,'COLL')
     655                 :          40 :              call wrtout(thermal_unit,msg,'COLL')
     656                 :             :            end if
     657                 :             :          end do
     658                 :             :        end if
     659                 :             : 
     660         [ +  + ]:          17 :        if(convth==1)exit
     661                 :             :      end do
     662                 :             :    end if
     663                 :             : 
     664         [ +  + ]:          14 :    if(.not.part2)then
     665                 :             :      ! Atomic temperature factor calculation
     666         [ +  + ]:          65 :      do iwchan=nwchan,1,-1
     667         [ +  + ]:          55 :        if (wgijcnv(iwchan))cycle
     668                 :             : 
     669                 :             :        ! Calculate gij(k|w) and Bij(k)
     670                 :             :        ! Check if the density of states changed by more than dostol
     671                 :          25 :        gijsum =zero
     672                 :          25 :        wgijcnv(iwchan)=.true.
     673         [ +  + ]:          25 :        if (ngrids>1) then
     674         [ +  + ]:          95 :          do iatom=1,natom
     675         [ +  + ]:         545 :            do ij=1,6
     676                 :         450 :              gijerr=zero
     677         [ +  + ]:      217020 :              do ichan=1,nchan2(iwchan)
     678                 :      216570 :                gijsum = gijsum + gij(ij,iatom,ichan,iwchan)
     679                 :             :                gijerr=gijerr&
     680                 :             : &               +abs(ggij(ij,iatom,ichan,iwchan)/gnorm&
     681                 :      217020 : &               -     gij(ij,iatom,ichan,iwchan))
     682                 :             :              end do
     683         [ -  + ]:         525 :              if(gijerr>anaddb_dtset%dostol) then
     684                 :           0 :                wgijcnv(iwchan)=.false.
     685                 :           0 :                exit
     686                 :             :              end if
     687                 :             :            end do
     688                 :             :          end do
     689                 :             :        else
     690                 :             :          gijerr=0.d0
     691                 :             :        end if
     692                 :             : 
     693                 :             : !      gij(k|w) is updated
     694                 :             : 
     695         [ +  + ]:       10935 :        do ichan=1,nchan2(iwchan)
     696         [ +  + ]:       72725 :          do iatom=1,natom
     697         [ +  + ]:      443440 :            do ij=1,6
     698                 :      432530 :              gij(ij,iatom,ichan,iwchan)=ggij(ij,iatom,ichan,iwchan)/(gnorm/(3*natom))
     699                 :             :            end do
     700                 :             : !if (iwchan==1) write (200+iatom,'(I6,6(E20.10,2x))') ichan, gij(1:6,iatom,ichan,iwchan)
     701                 :             :          end do
     702                 :             :        end do
     703                 :             : 
     704                 :             : !      Write gijerr for each q sampling and w width
     705                 :             : 
     706                 :          25 :        write(msg,'(a,a,i3,3i6,f10.5,f10.5)') ch10,&
     707                 :          25 : &       ' iwchan,igqpt(i),gijsum, gij error= ',&
     708                 :          50 : &       iwchan,igqpt2(1),igqpt2(2),igqpt2(3),gijsum,gijerr+tol10
     709                 :          25 :        call wrtout(std_out,msg,'COLL')
     710                 :             : 
     711                 :             : !      If the generalized DOS with a channel width is newly converged,
     712                 :             : !      print it out and calculate Bij(k).
     713         [ +  - ]:          35 :        if(wgijcnv(iwchan)) then
     714                 :             : 
     715         [ +  + ]:          25 :          if (ngrids==1) then
     716                 :           5 :            write(msg,'(a,i5,a)') ' gij with channel width=  ',iwchan,':'
     717                 :             :          else
     718                 :          20 :            write(msg,'(a,i5,a)') ' gij with channel width=  ',iwchan,' newly converged'
     719                 :             :          end if
     720                 :          25 :          call wrtout(iout,msg,'COLL')
     721                 :             : 
     722                 :          25 :          write(msg,'(a,2i3,3i6,f10.5)')'iatom,iwchan,igqpt2(i),gij error= ',&
     723                 :          50 : &         iatom,iwchan,igqpt2(1),igqpt2(2),igqpt2(3),gijerr+tol10
     724                 :          25 :          call wrtout(iout,msg,'COLL')
     725                 :             : 
     726         [ +  + ]:         275 :          do itemper=1,ntemper
     727                 :             : 
     728                 :             : !          Put zeroes for Bij(k)
     729         [ +  + ]:        1450 :            do iatom=1,natom
     730         [ +  + ]:        8650 :              do ij=1,6
     731                 :        7200 :                bbij(ij,iatom,itemper)=0._dp
     732                 :        8400 :                vij(ij,iatom,itemper)=0._dp
     733                 :             :              end do
     734                 :             :            end do
     735                 :             : 
     736                 :         250 :            tmp=anaddb_dtset%tempermin+anaddb_dtset%temperinc*dble(itemper-1)
     737                 :             : !          tmp in K
     738         [ +  - ]:         250 :            if (tmp < tol6) cycle
     739                 :             : 
     740                 :         250 :            dosinc=dble(iwchan)
     741                 :             : !
     742         [ +  + ]:      109375 :            do ichan=1,nchan2(iwchan)
     743                 :             : !
     744                 :             : !$wovert= \hbar*w / 2kT$, dimensionless
     745                 :      109100 :              wovert=dosinc*(dble(ichan)-half)/Ha_cmm1/(two*kb_HaK*tmp)
     746                 :      109100 :              expm2x=exp(-two*wovert)
     747         [ +  + ]:      727250 :              do iatom=1,natom
     748                 :             : !   factor contains 1 / (2 omega)
     749                 :             :                factor=Ha_cmm1/(two*dosinc*(dble(ichan)-half))    &
     750                 :      617900 : &               *(one+expm2x)/(one-expm2x) /amu(Crystal%typat(iatom))/amu_emass
     751                 :             : 
     752                 :             : !   this becomes * 0.5 * omega for the velocities
     753                 :             :                factorv=(half*dosinc*(dble(ichan)-half)/Ha_cmm1)    &
     754                 :      617900 : &               *(one+expm2x)/(one-expm2x) /amu(Crystal%typat(iatom))/amu_emass
     755                 :             : 
     756         [ +  + ]:     4434400 :                do ij=1,6
     757                 :     3707400 :                  bbij(ij,iatom,itemper)=bbij(ij,iatom,itemper) + factor*gij(ij,iatom,ichan,iwchan)
     758                 :     4325300 :                  vij(ij,iatom,itemper)=vij(ij,iatom,itemper) + factorv*gij(ij,iatom,ichan,iwchan)
     759                 :             :                end do
     760                 :             :              end do
     761                 :             : 
     762                 :             :            end do
     763                 :             : 
     764                 :             :          end do
     765                 :             : 
     766                 :             : !        B matrix is now in atomic unit in the Cartesian coordinates.
     767                 :             : !        Check if Bij(k) changed within tolerance.
     768                 :          25 :          convth=1
     769         [ +  + ]:          25 :          if (ngrids>1) then
     770         [ +  + ]:         112 :            do itemper=1,ntemper
     771         [ +  + ]:         309 :              do iatom=1,natom
     772         [ +  + ]:        1467 :                do ij=1,6
     773                 :        1261 :                  diffbb=bbij(ij,iatom,itemper)-bij(ij,iatom,itemper)
     774                 :             :                  !if (diffbb > 1d-10  .and. diffbb/bij(ij,iatom,itemper) > thmtol) then
     775                 :             :                  !  write(msg,'(a)' )' harmonic_thermo : Bij changes are larger than thmtol '
     776                 :             :                  !  call wrtout(std_out,msg,'COLL')
     777                 :             :                  !  convth=0
     778                 :             :                  !end if
     779         [ +  + ]:        1261 :                  if (diffbb > 1d-10) then
     780         [ +  - ]:         409 :                    if (bij(ij,iatom,itemper) /= zero) then
     781         [ +  + ]:         409 :                      if (diffbb/bij(ij,iatom,itemper) > thmtol) then
     782                 :          11 :                        write(msg,'(a)' )' harmonic_thermo : Bij changes are larger than thmtol '
     783                 :          11 :                        call wrtout(std_out,msg,'COLL')
     784                 :             :                        convth=0
     785                 :             :                      end if
     786                 :             :                    end if
     787                 :             :                  end if
     788                 :         206 :                  if(convth==0)exit
     789                 :             :                end do
     790         [ +  + ]:         309 :                if(convth==0)exit
     791                 :             :              end do
     792         [ +  + ]:         112 :              if(convth==0)exit
     793                 :             :            end do
     794                 :             :          end if
     795                 :             : 
     796   [ -  +  +  +  :        8700 :          bij=bbij ! save for next iteration
             +  +  +  + ]
     797                 :             : 
     798                 :             :          !Update Bij(k) and write them. B matrix printed in angstrom^2
     799                 :             :          !TODO : get rid of this version in the log and output file. Prefer
     800                 :             :          !external files
     801         [ +  + ]:          25 :          if (convth==1) then
     802                 :             :            write(msg, '(a,a,a)' )&
     803                 :          14 : &           ' B matrix elements as a function of T',ch10,&
     804                 :          28 : &           '    Angstrom^2, cartesian coordinates'
     805                 :          14 :            call wrtout(std_out,msg,'COLL')
     806                 :          14 :            call wrtout(iout,msg,'COLL')
     807                 :             : 
     808         [ +  + ]:         154 :            do itemper=1,ntemper
     809                 :             : !            tmp in K
     810                 :         140 :              tmp=anaddb_dtset%tempermin+anaddb_dtset%temperinc*dble(itemper-1)
     811         [ +  + ]:         784 :              do iatom=1,natom
     812                 :             :                write(iout,'(2i3,es11.3,6es12.4)')&
     813                 :         630 : &               iwchan,iatom,tmp+tol10,&
     814                 :         630 : &               Bohr_Ang**2*bij(1,iatom,itemper)+tol10,&
     815                 :         630 : &               Bohr_Ang**2*bij(2,iatom,itemper)+tol10,&
     816                 :         630 : &               Bohr_Ang**2*bij(3,iatom,itemper)+tol10,&
     817                 :         630 : &               Bohr_Ang**2*bij(4,iatom,itemper)+tol10,&
     818                 :         630 : &               Bohr_Ang**2*bij(5,iatom,itemper)+tol10,&
     819                 :        1400 : &               Bohr_Ang**2*bij(6,iatom,itemper)+tol10
     820                 :             :              end do ! end loop over natom
     821                 :             :            end do ! end loop over ntemper
     822                 :             : 
     823                 :             : !        Mean square velocity matrix printed in angstrom^2/picosec^2
     824                 :             :            write(msg, '(a,a,a)' )&
     825                 :          14 : &           ' <vel^2> matrix elements as a function of T',ch10,&
     826                 :          28 : &           '    Angstrom^2/(picosec)^2, cartesian coordinates'
     827                 :          14 :            call wrtout(std_out,msg,'COLL')
     828                 :          14 :            call wrtout(iout,msg,'COLL')
     829                 :             : 
     830         [ +  + ]:         154 :            do itemper=1,ntemper
     831                 :             : !            tmp in K
     832                 :         140 :              tmp=anaddb_dtset%tempermin+anaddb_dtset%temperinc*float(itemper-1)
     833         [ +  + ]:         784 :              do iatom=1,natom
     834         [ +  + ]:        4410 :                vij(:,iatom,itemper)=Bohr_Ang**2*vij(:,iatom,itemper)/(Time_Sec*1.0e12)**2
     835                 :             : !              The following check zeros out <v^2> if it is very small, in order to
     836                 :             : !              avoid numerical noise being interpreted by the automatic tests as
     837                 :             : !              something real. Note also that we compare it in
     838                 :             : !              absolute value, that's because if any of the phonon frequencies are
     839                 :             : !              computed as negative, <v^2> can take a negative value.
     840         [ +  + ]:        4410 :                do icomp=1, 6
     841         [ +  + ]:        4410 :                  if (abs(vij(icomp,iatom,itemper)) < 1.0e-12) vij(icomp,iatom,itemper)=zero
     842                 :             :                end do
     843                 :             :                write(iout,'(2i3,es11.3,6es12.4)')&
     844                 :         630 : &               iwchan,iatom,tmp+tol10,&
     845                 :         630 : &               vij(1,iatom,itemper),&
     846                 :         630 : &               vij(2,iatom,itemper),&
     847                 :         630 : &               vij(3,iatom,itemper),&
     848                 :         630 : &               vij(4,iatom,itemper),&
     849                 :         630 : &               vij(5,iatom,itemper),&
     850                 :        1400 : &               vij(6,iatom,itemper)
     851                 :             :              end do ! end loop over natom
     852                 :             :            end do ! end loop over ntemper
     853                 :             :          end if ! end check on convergence
     854                 :             : 
     855                 :             : 
     856                 :             :          ! keep this one !!!!!!!!!!!!!!!!!!
     857                 :             :          if (convth==1) then
     858                 :             :            write(msg, '(a,a,a)' )&
     859                 :          14 : &           '# B matrix elements as a function of T, for each atom, and smallest omega channel width',ch10,&
     860                 :          28 : &           '#    Angstrom^2, cartesian coordinates'
     861                 :          14 :            call wrtout(bij_unit,msg,'COLL')
     862         [ +  + ]:          77 :            do iatom=1,natom
     863                 :          63 :              write(msg, '(2a,i10)' ) ch10, '# for atom ', iatom
     864                 :          63 :              call wrtout(bij_unit,msg,'COLL')
     865         [ +  + ]:         707 :              do itemper=1,ntemper
     866                 :             : !              tmp in K
     867                 :         630 :                tmp=anaddb_dtset%tempermin+anaddb_dtset%temperinc*dble(itemper-1)
     868                 :             :                write(msg,'(es11.3,6es12.4)')&
     869                 :         630 : &               tmp,&
     870                 :         630 : &               Bohr_Ang**2*bij(1,iatom,itemper),&
     871                 :         630 : &               Bohr_Ang**2*bij(2,iatom,itemper),&
     872                 :         630 : &               Bohr_Ang**2*bij(3,iatom,itemper),&
     873                 :         630 : &               Bohr_Ang**2*bij(4,iatom,itemper),&
     874                 :         630 : &               Bohr_Ang**2*bij(5,iatom,itemper),&
     875                 :        1260 : &               Bohr_Ang**2*bij(6,iatom,itemper)
     876                 :         693 :                call wrtout(bij_unit,msg,'COLL')
     877                 :             :              end do ! end loop over ntemper
     878                 :             :            end do ! end loop over natom
     879                 :             : 
     880                 :             : !        Mean square velocity matrix printed in angstrom^2/picosec^2
     881                 :             :            write(msg, '(a,a,a)' )&
     882                 :          14 : &           '# <vel^2> matrix elements as a function of T, for each atom, and smallest channel width',ch10,&
     883                 :          28 : &           '#    Angstrom^2/(picosec)^2, cartesian coordinates'
     884                 :          14 :            call wrtout(vij_unit,msg,'COLL')
     885                 :             : 
     886         [ +  + ]:          77 :            do iatom=1,natom
     887                 :          63 :              write(msg, '(2a,i10)' ) ch10, '# for atom ', iatom
     888                 :          63 :              call wrtout(vij_unit,msg,'COLL')
     889         [ +  + ]:         707 :              do itemper=1,ntemper
     890                 :             : !            tmp in K
     891                 :         630 :                tmp=anaddb_dtset%tempermin+anaddb_dtset%temperinc*float(itemper-1)
     892         [ +  + ]:        4410 :                vij(:,iatom,itemper)=Bohr_Ang**2*vij(:,iatom,itemper)/(Time_Sec*1.0e12)**2
     893                 :             : 
     894                 :             : !            The following check zeros out <v^2> if it is very small, in order to
     895                 :             : !            avoid numerical noise being interpreted by the automatic tests as
     896                 :             : !            something real. Note also that we compare it in
     897                 :             : !            absolute value, that's because if any of the phonon frequencies are
     898                 :             : !            computed as negative, <v^2> can take a negative value.
     899         [ +  + ]:        4410 :                do icomp=1, 6
     900         [ +  + ]:        4410 :                  if (abs(vij(icomp,iatom,itemper)) < 1.0e-12) vij(icomp,iatom,itemper)=zero
     901                 :             :                end do
     902                 :             :                write(vij_unit,'(es11.3,6es12.4)')&
     903                 :         630 : &               tmp,&
     904                 :         630 : &               vij(1,iatom,itemper),&
     905                 :         630 : &               vij(2,iatom,itemper),&
     906                 :         630 : &               vij(3,iatom,itemper),&
     907                 :         630 : &               vij(4,iatom,itemper),&
     908                 :         630 : &               vij(5,iatom,itemper),&
     909                 :        1323 : &               vij(6,iatom,itemper)
     910                 :             :              end do ! end loop over ntemper
     911                 :             :            end do ! end loop over natom
     912                 :             :          end if ! end check on convergence
     913                 :             : 
     914                 :             :          if(convth==1)part2=.true.
     915                 :             : 
     916                 :             :        end if ! End of test on wgijcnv
     917                 :             :      end do ! End of loop over iwchan
     918                 :             :    end if ! End of part2
     919                 :             : 
     920         [ +  + ]:          14 :    if(part1.and.part2)exit
     921                 :             : 
     922         [ -  + ]:          12 :    ABI_FREE(indqpt1)
     923         [ -  + ]:          12 :    ABI_FREE(qpt2)
     924         [ -  + ]:          12 :    ABI_FREE(spqpt2)
     925         [ -  + ]:          12 :    ABI_FREE(wtq)
     926         [ -  + ]:          30 :    ABI_FREE(wtq2)
     927                 :             : 
     928                 :             :  end do ! End of the Loop on the q point grids
     929                 :             : 
     930         [ -  + ]:           4 :  ABI_FREE(bbij)
     931         [ -  + ]:           4 :  ABI_FREE(bij)
     932         [ -  + ]:           4 :  ABI_FREE(energy)
     933         [ -  + ]:           4 :  ABI_FREE(energy0)
     934         [ -  + ]:           4 :  ABI_FREE(entropy)
     935         [ -  + ]:           4 :  ABI_FREE(entropy0)
     936         [ -  + ]:           4 :  ABI_FREE(free)
     937         [ -  + ]:           4 :  ABI_FREE(free0)
     938         [ -  + ]:           4 :  ABI_FREE(gdos)
     939         [ -  + ]:           4 :  ABI_FREE(gg)
     940         [ -  + ]:           4 :  ABI_FREE(gg_sum)
     941         [ -  + ]:           4 :  ABI_FREE(gg_rest)
     942         [ -  + ]:           4 :  ABI_FREE(ggij)
     943         [ -  + ]:           4 :  ABI_FREE(gij)
     944         [ -  + ]:           4 :  ABI_FREE(nchan2)
     945         [ -  + ]:           4 :  ABI_FREE(spheat)
     946         [ -  + ]:           4 :  ABI_FREE(spheat0)
     947         [ -  + ]:           4 :  ABI_FREE(vij)
     948         [ -  + ]:           4 :  ABI_FREE(wgcnv)
     949         [ -  + ]:           4 :  ABI_FREE(wgijcnv)
     950         [ +  + ]:           4 :  if(allocated(indqpt1)) then
     951                 :           2 :    ABI_FREE(indqpt1)
     952                 :             :  end if
     953         [ +  + ]:           4 :  if(allocated(qpt2)) then
     954                 :           2 :    ABI_FREE(qpt2)
     955                 :             :  end if
     956         [ +  + ]:           4 :  if(allocated(spqpt2)) then
     957                 :           2 :    ABI_FREE(spqpt2)
     958                 :             :  end if
     959         [ +  + ]:           4 :  if(allocated(wtq)) then
     960                 :           2 :    ABI_FREE(wtq)
     961                 :             :  end if
     962         [ +  + ]:           4 :  if(allocated(wtq2)) then
     963                 :           2 :    ABI_FREE(wtq2)
     964                 :             :  end if
     965         [ -  + ]:           4 :  ABI_FREE(gw)
     966         [ -  + ]:           4 :  ABI_FREE(wme)
     967                 :             : 
     968         [ -  + ]:           4 :  if(.not.part1)then
     969                 :             :    write(msg, '(a,a,a,a,a,a,a,a,a)' )&
     970                 :           0 : &   'No thermodynamical function is printed out :',ch10,&
     971                 :           0 : &   'the tolerance level that was asked ',ch10,&
     972                 :           0 : &   'has not been match with the grids specified.',ch10,&
     973                 :           0 : &   'Action: in the input file, increase the resolution',ch10,&
     974                 :           0 : &   'of grids ng2qpt, or decrease the accuracy requirement thmtol.'
     975                 :           0 :    ABI_ERROR(msg)
     976                 :             :  end if
     977                 :             : 
     978         [ +  + ]:           4 :  if(.not.part2)then
     979                 :             :    write(msg,'(a,a,a,a,a,a,a,a,a)')&
     980                 :           2 : &   'No atomic factor tensor is printed out :',ch10,&
     981                 :           2 : &   'the tolerance level that was asked ',ch10,&
     982                 :           2 : &   'has not been match with the grids specified.',ch10,&
     983                 :           2 : &   'Action: in the input file, increase the resolution',ch10,&
     984                 :           4 : &   'of grids ng2qpt, or decrease the accuracy requirement thmtol.'
     985                 :           2 :    ABI_WARNING(msg)
     986                 :             :  end if
     987                 :             : 
     988                 :           4 :  close (thermal_unit)
     989                 :           4 :  close (bij_unit)
     990                 :           4 :  close (vij_unit)
     991                 :             : 
     992                 :             : end subroutine harmonic_thermo
     993                 :             : !!***
     994                 :             : 
     995                 :             : end module m_harmonic_thermo
     996                 :             : !!***
        

Generated by: LCOV version 2.3-1