LCOV - code coverage report
Current view: top level - src/77_ddb - m_ddb_diel.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 82.0 % 344 282
Test Date: 2026-11-12 14:41:44 Functions: 100.0 % 4 4
Branches: 66.6 % 500 333

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_ddb_diel
       2                 :             : !! NAME
       3                 :             : !! m_ddb_diel
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !! This module provides routines for the calculation of the dielectric constant (anaddb)
       7                 :             : !!
       8                 :             : !! COPYRIGHT
       9                 :             : !!  Copyright (C) 1999-2026 ABINIT group (XG,XW, MVeithen, EB)
      10                 :             : !!  This file is distributed under the terms of the
      11                 :             : !!  GNU General Public License, see ~abinit/COPYING
      12                 :             : !!  or http://www.gnu.org/copyleft/gpl.txt .
      13                 :             : !!
      14                 :             : !! SOURCE
      15                 :             : 
      16                 :             : #if defined HAVE_CONFIG_H
      17                 :             : #include "config.h"
      18                 :             : #endif
      19                 :             : 
      20                 :             : #include "abi_common.h"
      21                 :             : 
      22                 :             : module m_ddb_diel
      23                 :             : 
      24                 :             :  use defs_basis
      25                 :             :  use m_errors
      26                 :             :  use m_xmpi
      27                 :             :  use m_abicore
      28                 :             :  use m_ddb
      29                 :             :  use m_nctk
      30                 :             :  use netcdf
      31                 :             : 
      32                 :             :  use m_anaddb_dataset, only : anaddb_dataset_type
      33                 :             :  use m_crystal,        only : crystal_t
      34                 :             : 
      35                 :             :  implicit none
      36                 :             : 
      37                 :             :  private
      38                 :             : !!***
      39                 :             : 
      40                 :             :  public :: ddb_diel
      41                 :             :  public :: alignph
      42                 :             : !!***
      43                 :             : 
      44                 :             : contains
      45                 :             : !!***
      46                 :             : 
      47                 :             : !!****f* ABINIT/ddb_diel
      48                 :             : !!
      49                 :             : !! NAME
      50                 :             : !! ddb_diel
      51                 :             : !!
      52                 :             : !! FUNCTION
      53                 :             : !! Get the frequency-dependent dielectric matrix, as well as the
      54                 :             : !! oscillator strengths and mode effective charges,
      55                 :             : !! and reflectivities (without damping)
      56                 :             : !! See the definitions Eq.(53-54) in PRB55, 10355 (1997) [[cite:Gonze1997a]].
      57                 :             : !!
      58                 :             : !! INPUTS
      59                 :             : !! amu(ntypat)=mass of the atoms (atomic mass unit)
      60                 :             : !! anaddb_dtset= (derived datatype) contains all the input variables
      61                 :             : !! matrix (diagonal in the atoms)
      62                 :             : !! displ(2,3*natom,3*natom)=
      63                 :             : !!  the displacements of atoms in cartesian coordinates.
      64                 :             : !!  The first index means either the real or the imaginary part,
      65                 :             : !!  The second index runs on the direction and the atoms displaced
      66                 :             : !!  The third index runs on the modes.
      67                 :             : !! d2cart(2,3,mpert,3,mpert)=dynamical matrix, effective charges, dielectric tensor,... all in cartesian coordinates
      68                 :             : !! iout=unit number for outputs
      69                 :             : !! lst(3*nph2l)=log. of product of frequencies**2, needed to calculate
      70                 :             : !!  the generalized Lyddane-Sachs-Teller relation at zero frequency
      71                 :             : !! mpert =maximum number of ipert
      72                 :             : !! natom=number of atoms in unit cell
      73                 :             : !! nph2l=input variable from anaddb_dtset, needed to dimension lst
      74                 :             : !! phfrq(3*natom)=phonon frequencies (square root of the dynamical
      75                 :             : !!  matrix eigenvalues, except if these are negative, and in this
      76                 :             : !!  case, give minus the square root of the absolute value
      77                 :             : !!  of the matrix eigenvalues). Hartree units.
      78                 :             : !! comm=MPI communicator.
      79                 :             : !! ncid=the id of the open NetCDF file. Set to nctk_noid if netcdf output is not wanted.
      80                 :             : !!
      81                 :             : !! OUTPUT
      82                 :             : !! fact_oscstr(2,3,3*natom)=oscillator strengths for the different eigenmodes,
      83                 :             : !!  for different direction of the electric field;
      84                 :             : !! dielt_rlx(3,3) relaxed ion (zero frequency) dielectric tensor.
      85                 :             : !!
      86                 :             : !! NOTES
      87                 :             : !! 1. The phonon frequencies phfrq should correspond to the
      88                 :             : !! wavevector at Gamma, without any non-analyticities.
      89                 :             : !! 2. Should clean for no imaginary part ...
      90                 :             : !! This routine should be used only by one processor.
      91                 :             : !! 3. frdiel(3,3,nfreq)= frequency-dependent dielectric tensor
      92                 :             : !! mode effective charges for the different eigenmodes,
      93                 :             : !! for different direction of the electric field
      94                 :             : !!
      95                 :             : !! SOURCE
      96                 :             : 
      97                 :          26 : subroutine ddb_diel(Crystal,amu,anaddb_dtset,dielt_rlx,displ,d2cart,epsinf,fact_oscstr,&
      98                 :          26 : & iout,lst,mpert,natom,nph2l,phfrq,comm,ncid)
      99                 :             : 
     100                 :             : !Arguments -------------------------------
     101                 :             : !scalars
     102                 :             :  integer,intent(in) :: iout,mpert,natom,nph2l,comm,ncid
     103                 :             :  type(crystal_t),intent(in) :: Crystal
     104                 :             :  type(anaddb_dataset_type),intent(in) :: anaddb_dtset
     105                 :             :  real(dp),intent(in) :: lst(nph2l+1)
     106                 :             : 
     107                 :             : !arrays
     108                 :             :  real(dp),intent(in) :: amu(Crystal%ntypat),d2cart(2,3,mpert,3,mpert)
     109                 :             :  real(dp),intent(in) :: phfrq(3*natom),epsinf(3,3)
     110                 :             :  real(dp),intent(inout) :: displ(2,3*natom,3*natom)
     111                 :             :  real(dp),intent(out) :: dielt_rlx(3,3),fact_oscstr(2,3,3*natom)
     112                 :             : 
     113                 :             : !Local variables -------------------------
     114                 :             : !scalars
     115                 :             :  integer,parameter :: master=0
     116                 :             :  integer :: dieflag,idir1,idir2,ifreq,ii,imode,iphl2,nfreq
     117                 :             :  integer :: nprocs,my_rank,ncerr
     118                 :             :  real(dp) :: afreq,difffr,eps,q2,ucvol
     119                 :             :  character(len=500) :: message
     120                 :             : !arrays
     121                 :             :  real(dp) :: qphon(3),refl(3)
     122                 :          26 :  real(dp),allocatable :: frdiel(:,:,:),modez(:,:,:),oscstr(:,:,:,:),dielt_modedecompo(:,:,:)
     123                 :             : 
     124                 :             : ! *********************************************************************
     125                 :             : 
     126                 :          26 :  nprocs = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
     127                 :             : 
     128                 :          26 :  dieflag=anaddb_dtset%dieflag
     129                 :          26 :  nfreq=anaddb_dtset%nfreq
     130                 :             : 
     131                 :          26 :  ucvol = Crystal%ucvol
     132                 :             : 
     133                 :             : 
     134                 :             : ! frdiel(3,3,nfreq)= frequency-dependent dielectric tensor
     135                 :             : ! modez=mode effective charge
     136   [ -  +  +  -  :          78 :  ABI_MALLOC(frdiel,(3,3,nfreq))
          +  -  +  -  -  
                +  -  + ]
     137   [ +  -  -  +  :         104 :  ABI_MALLOC(oscstr,(2,3,3,3*natom))
          +  -  +  -  +  
             -  -  +  -  
                      + ]
     138   [ -  +  +  -  :          78 :  ABI_MALLOC(modez,(2,3,3*natom))
          +  -  +  -  -  
                +  -  + ]
     139   [ -  +  +  -  :          78 :  ABI_MALLOC(dielt_modedecompo,(3,3,3*natom))
          +  -  +  -  -  
                +  -  + ]
     140                 :             : 
     141                 :             : !In case only the electronic dielectric constant should be printed
     142         [ +  + ]:          26 :  if (dieflag==2) then
     143                 :           7 :    call ddb_diel_elec(iout,epsinf)
     144                 :             :  else
     145                 :             : !  In case the ionic contribution to the dielectric tensor is asked
     146         [ +  + ]:          19 :    if (dieflag/=2 .and. nph2l==0) then
     147                 :             : !   Check if the alignement of phonon modes eigenvector is requested from the input flag alphon;
     148                 :             : !   useful in case of degenerate modes
     149         [ +  + ]:          10 :      if (anaddb_dtset%alphon > 0) then
     150                 :             :        write(message, '(3a)' )&
     151                 :           3 :         ' The alphon input variable is non-zero, will mix the degenerate phonon modes',ch10,&
     152                 :           6 :         ' in order to align the mode effective charges with the cartesian axes.'
     153                 :           3 :        call wrtout(std_out,message,'COLL')
     154                 :           3 :        call wrtout(iout,message,'COLL')
     155                 :           3 :        call alignph(amu,displ,d2cart,mpert,natom,Crystal%ntypat,phfrq,Crystal%typat)
     156                 :             :      end if ! alignment of the phonon eigenvectors
     157                 :             : 
     158                 :             : !    Compute the mode effective charge and oscillator strength
     159                 :          10 :      call ddb_oscstr(displ,d2cart,fact_oscstr,oscstr,modez,iout,mpert,natom,phfrq,ncid,my_rank)
     160                 :             : 
     161                 :             : !      Calculation of epsilon_r (Eq.55 PRB 55, 10355)
     162                 :             : !      Check the acousticity of the three lowest modes, assuming
     163                 :             : !      that they are ordered correctly
     164         [ -  + ]:          10 :        if (abs(phfrq(1))>abs(phfrq(4)))then
     165                 :             : !        This means that there is at least one mode with truly negative frequency
     166                 :             :          write(message, '(12a,4es16.8)' )&
     167                 :           0 :            'The lowest mode appears to be a "true" negative mode,',ch10,&
     168                 :           0 :            'and not an acoustic mode. This precludes the computation',ch10,&
     169                 :           0 :            'of the frequency-dependent dielectric tensor.',ch10,&
     170                 :           0 :            'Action : likely there is no action to be taken, although you,',ch10,&
     171                 :           0 :            'could try to raise your convergence parameters (ecut and k-points).',ch10,&
     172                 :           0 :            'For your information, here are the four lowest frequencies :',ch10,&
     173                 :           0 :            (phfrq(ii),ii=1,4)
     174                 :           0 :          ABI_ERROR(message)
     175                 :             :        end if
     176                 :             : 
     177                 :             : !      Compute the relaxed ion dielectric tensor
     178         [ +  + ]:          40 :        do idir1=1,3
     179         [ +  + ]:         130 :          do idir2=1,3
     180                 :             : !          The electronic contribution to epsilon is added
     181                 :          90 :            dielt_rlx(idir1,idir2)=epsinf(idir1,idir2)
     182                 :             : !          calculation of the phonon contribution (ionic) to epsilon
     183         [ +  + ]:        1227 :            do imode=4,3*natom
     184                 :             : !            Note that the acoustic modes are not included : their
     185                 :             : !            oscillator strength should be exactly zero
     186                 :             : !            Also, only the real part of oscstr is taken into account:
     187                 :             : !            the possible imaginary parts of degenerate modes
     188                 :             : !            will cancel.
     189                 :             :              dielt_rlx(idir1,idir2)=dielt_rlx(idir1,idir2)+&
     190                 :        1107 : &             oscstr(1,idir1,idir2,imode) / (phfrq(imode)**2)*four_pi/ucvol
     191                 :             : !            Mode decomposition of epsilon
     192         [ -  + ]:        1197 :              if (dieflag==3)then
     193                 :           0 :                dielt_modedecompo(idir1,idir2,imode)=oscstr(1,idir1,idir2,imode) / (phfrq(imode)**2)*four_pi/ucvol
     194                 :             :              endif ! mode decompo of epsilon
     195                 :             : !DEBUG
     196                 :             : !         if(idir1==1 .and. idir2==2)then
     197                 :             : !           write(std_out,'(a,i4,a,3es16.6)')'imode=',imode,' dielt_rlx(idir1,idir2),oscstr(1,idir1,idir2,imode),phfrq(imode)=',&
     198                 :             : !&            dielt_rlx(idir1,idir2),oscstr(1,idir1,idir2,imode),phfrq(imode)
     199                 :             : !         endif
     200                 :             : !ENDDEBUG
     201                 :             :            end do ! imode
     202                 :             :          end do ! idir2
     203                 :             :        end do ! idir1
     204                 :             : 
     205                 :             :        ! Print the electronic dielectric tensor
     206                 :          10 :        call ddb_diel_elec(iout,epsinf)
     207                 :             : 
     208                 :             :        ! Print the relaxed ion dielectric tensor
     209                 :          10 :        write(message,'(a,a)') ch10,' Relaxed ion dielectric tensor'
     210                 :          10 :        call wrtout(std_out,message,'COLL')
     211                 :          10 :        call wrtout(iout,message,'COLL')
     212                 :             : 
     213         [ +  + ]:          40 :        do idir1=1,3
     214                 :          30 :          write(message,'(3f16.8)')(dielt_rlx(idir1,idir2),idir2=1,3)
     215                 :          30 :          call wrtout(std_out,message,'COLL')
     216                 :          40 :          call wrtout(iout,message,'COLL')
     217                 :             :        end do
     218                 :          10 :        call wrtout(iout, " ",'COLL')
     219                 :          10 :        call wrtout(std_out, " ",'COLL')
     220                 :             : 
     221                 :             : !      Mode decompo of epsilon
     222         [ -  + ]:          10 :        if (dieflag==3) then
     223                 :           0 :          write(message,'(a,a,a,a)') ch10,' Mode by mode decomposition of the ionic dielectric tensor',&
     224                 :           0 :                                     ch10,' (the electronic contribution is not included)'
     225                 :           0 :          call wrtout(std_out,message,'COLL')
     226                 :           0 :          call wrtout(iout,message,'COLL')
     227         [ #  # ]:           0 :          do imode=4,3*natom
     228                 :           0 :            write(message,'(a,a,i4,a,es14.6,a,a,3f8.3)') ch10,' Mode number ',imode, '    freq = ',phfrq(imode),' Ha', &
     229   [ #  #  #  # ]:           0 :                                                           '   Mode Z* (|x|, |y|, |z|)', (abs(modez(1,idir1,imode)),idir1=1,3)
     230                 :           0 :            call wrtout(std_out,message,'COLL')
     231                 :           0 :            call wrtout(iout,message,'COLL')
     232         [ #  # ]:           0 :            do idir1=1,3
     233                 :             :            ! write(message,'(a,a,i4)') ch10,' Mode number 2',imode
     234                 :           0 :              write(message,'(3f16.8)')(dielt_modedecompo(idir1,idir2,imode),idir2=1,3)
     235                 :           0 :              call wrtout(std_out,message,'COLL')
     236                 :           0 :              call wrtout(iout,message,'COLL')
     237                 :             :            end do
     238                 :             :          end do
     239                 :             :        endif ! mode decompo of epsilon
     240                 :             : 
     241                 :             :        ! write the relaxed ion dielectric tensor to the netcdf
     242         [ +  - ]:          10 :        if (ncid /= nctk_noid) then
     243                 :             :          ncerr = nctk_def_arrays(ncid, [nctkarr_t("emacro_cart_rlx", "dp", &
     244         [ +  + ]:          20 :          "number_of_cartesian_directions, number_of_cartesian_directions")],defmode=.True.)
     245         [ -  + ]:          10 :          NCF_CHECK(ncerr)
     246         [ -  + ]:          10 :          NCF_CHECK(nctk_set_datamode(ncid))
     247         [ -  + ]:          10 :          NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "emacro_cart_rlx"), dielt_rlx))
     248                 :             :        end if
     249                 :             : 
     250                 :             : !    Frequency-dependent dielectric tensor case
     251         [ +  + ]:          10 :      if(dieflag==1) then
     252                 :           8 :        write(message,'(4a)') ch10,ch10,' Calculate the freq. dep. dielectric constant',ch10
     253                 :           8 :        call wrtout(std_out,message,'COLL')
     254                 :           8 :        write(message,'(3a)') ch10,' Frequency dependent dielectric constant:',ch10
     255                 :           8 :        call wrtout(iout,message,'COLL')
     256                 :             : 
     257                 :             : !      Check the possibility of asking the frequency-dependent
     258                 :             : !      dielectric tensor (there should be more than one atom in the unit cell)
     259                 :             : !      EB: this check is not in any automatic test
     260         [ -  + ]:           8 :        if(natom==1)then
     261                 :             :          write(message, '(6a)' )&
     262                 :           0 :            ' ddb_diel : WARNING -',ch10,&
     263                 :           0 :            '  When there is only one atom in the unit cell',ch10,&
     264                 :           0 :            '  cell, the dielectric tensor is frequency-independent.'!,&
     265                 :             : !           '  Consequently, dieflag has been reset to 2 . '
     266                 :           0 :          call wrtout(std_out,message,'COLL')
     267                 :           0 :          call wrtout(iout,message,'COLL')
     268                 :             :        end if
     269                 :             : 
     270                 :           8 :        difffr=zero
     271         [ +  + ]:           8 :        if(nfreq>1)difffr=(anaddb_dtset%frmax-anaddb_dtset%frmin)/(nfreq-1)
     272                 :             : 
     273   [ -  +  -  + ]:           2 :        if (nfreq>10 .and. my_rank == master) then
     274                 :             :          write(iout, '(a,a,a,a,a,a,a,a)' )&
     275                 :           2 :           ' ddb_diel : the number of frequencies is larger',&
     276                 :           2 :           ' than 10 => I will consider only',ch10,&
     277                 :           2 :           ' the three principal directions, assume that the tensor',ch10,&
     278                 :           2 :           ' is diagonalized, and give dielectric constant and ',ch10,&
     279                 :           4 :           ' reflectivities.'
     280                 :             :          write(iout, '(a,a)' )&
     281                 :           2 :           ' Frequency(Hartree)    Dielectric constant   ',&
     282                 :           4 :           '             Reflectivity    '
     283                 :             :          write(iout, '(a,a)' )&
     284                 :           2 :           '                     x           y          z',&
     285                 :           4 :           '          x        y        z'
     286                 :             :        end if
     287                 :             : 
     288                 :             : !      Loop on frequencies
     289         [ +  + ]:         214 :        do ifreq=1,nfreq
     290                 :         206 :          afreq=anaddb_dtset%frmin+difffr*(ifreq-1)
     291         [ +  + ]:         824 :          do idir1=1,3
     292         [ +  + ]:        2678 :            do idir2=1,3
     293                 :        1854 :              frdiel(idir1,idir2,ifreq)=epsinf(idir1,idir2)
     294         [ +  + ]:        8817 :              do imode=4,3*natom
     295                 :             : !              Note that the acoustic modes are not included : their
     296                 :             : !              oscillator strength should be exactly zero
     297                 :             : !              Also, only the real part of oscstr is taken into account:
     298                 :             : !              the possible imaginary parts of degenerate modes
     299                 :             : !              will cancel.
     300                 :             :                frdiel(idir1,idir2,ifreq)=frdiel(idir1,idir2,ifreq)+&
     301                 :        8199 : &               oscstr(1,idir1,idir2,imode) / (phfrq(imode)**2-afreq**2)*four_pi/ucvol
     302                 :             :              end do
     303                 :             :            end do
     304                 :             :          end do
     305                 :             : 
     306                 :             :         ! Write all this information (actually, there should be a choice of units for the frequencies ...
     307         [ +  + ]:         214 :         if (nfreq>10) then
     308         [ +  + ]:         800 :           do idir1=1,3
     309         [ +  + ]:         800 :             if(frdiel(idir1,idir1,ifreq)<=zero)then
     310                 :          24 :               refl(idir1)=one
     311                 :             :             else
     312                 :             : !             See Gervais and Piriou PRB11,3944(1975) [[cite:Gervais1975]].
     313                 :         576 :               refl(idir1)=( (sqrt(frdiel(idir1,idir1,ifreq)) -one) /(sqrt(frdiel(idir1,idir1,ifreq)) +one) )**2
     314                 :             :             end if
     315                 :             :           end do
     316         [ +  - ]:         200 :           if (my_rank == master) then
     317   [ +  -  +  + ]:         800 :             write(iout, '(7es12.4)' )afreq,(frdiel(idir1,idir1,ifreq),idir1=1,3),(refl(idir1),idir1=1,3)
     318                 :             :           end if
     319                 :             : 
     320                 :             :         else
     321         [ +  - ]:           6 :           if (my_rank == master) then
     322                 :           6 :             write(iout, '(a,es12.4,a)' )' Full dielectric tensor at frequency',afreq,' Hartree'
     323         [ +  + ]:          24 :             do idir1=1,3
     324                 :          24 :               write(iout, '(3f16.8)' ) (frdiel(idir1,idir2,ifreq),idir2=1,3)
     325                 :             :             end do
     326                 :           6 :             write(iout, '(a)' )' '
     327                 :             :           end if
     328                 :             :         end if
     329                 :             : 
     330                 :             :       end do ! End of the loop on frequencies
     331                 :             :     end if ! End the condition on frequency-dependent dielectric tensor (dieflag=1)
     332                 :             :   end if ! dieflag/=2 .and. nph2l==0
     333                 :             : end if
     334                 :             : 
     335                 :             : !Calculation of the Lyddane-Sachs-Teller value of the dielectric constant at zero frequency
     336   [ +  +  +  - ]:          26 : if(nph2l/=0 .and. dieflag/=2) then
     337                 :             : 
     338                 :             : !  Prepare the output
     339                 :           9 :    write(message, '(a,a,a,a)' ) ch10,&
     340                 :           9 :     ' Generalized Lyddane-Sachs-Teller relation at zero frequency :',ch10,&
     341                 :          18 :     ' Direction                     Dielectric constant'
     342                 :           9 :    call wrtout(std_out,message,'COLL')
     343                 :           9 :    call wrtout(iout,message,'COLL')
     344                 :             : 
     345                 :             : !  Examine every wavevector in the phonon list
     346         [ +  + ]:          23 :    do iphl2=1,anaddb_dtset%nph2l
     347                 :             : 
     348         [ +  + ]:          56 :      qphon(1:3)=anaddb_dtset%qph2l(1:3,iphl2)
     349                 :             : 
     350   [ +  +  +  +  :          23 :      if(abs(qphon(1))>DDB_QTOL .or. abs(qphon(2))>DDB_QTOL .or. abs(qphon(3))>DDB_QTOL)then
                   +  - ]
     351                 :          14 :        q2=qphon(1)**2+qphon(2)**2+qphon(3)**2
     352                 :             :        eps=qphon(1)**2*epsinf(1,1)+qphon(2)**2*epsinf(2,2)+&
     353                 :             : &      qphon(3)**2*epsinf(3,3)+ 2* ( qphon(1)*qphon(2)*epsinf(1,2)+&
     354                 :          14 : &      qphon(1)*qphon(3)*epsinf(1,3)+qphon(2)*qphon(3)*epsinf(2,3))
     355                 :          14 :        eps=eps/q2*exp(lst(iphl2)-lst(anaddb_dtset%nph2l+1))
     356         [ +  - ]:          14 :        if (my_rank == master) then
     357                 :          14 :          write(iout, '(3f10.5,f16.8)' )qphon,eps
     358                 :          14 :          write(std_out,'(3f10.5,f16.8)' )qphon,eps
     359                 :             :        end if
     360                 :             :      end if
     361                 :             :    end do
     362                 :             :  end if ! End of the condition of nph2l does not vanish for Lyddane-Sachs-Teller
     363                 :             : 
     364                 :             : 
     365         [ -  + ]:          26 :  ABI_FREE(frdiel)
     366         [ -  + ]:          26 :  ABI_FREE(modez)
     367         [ -  + ]:          26 :  ABI_FREE(oscstr)
     368         [ -  + ]:          26 :  ABI_FREE(dielt_modedecompo)
     369                 :             : 
     370                 :          26 : end subroutine ddb_diel
     371                 :             : !!***
     372                 :             : 
     373                 :             : 
     374                 :             : 
     375                 :             : !!****f* ABINIT/ddb_diel_elec
     376                 :             : !!
     377                 :             : !! NAME
     378                 :             : !! ddb_diel_elec
     379                 :             : !!
     380                 :             : !! FUNCTION
     381                 :             : !! Print the electronic dielectric constant (clamped ions)
     382                 :             : !!
     383                 :             : !! INPUTS
     384                 :             : !! iout=unit number for outputs
     385                 :             : !! epsinf(3,3)= epsilon^infty = electronic contribution to the
     386                 :             : !!  dielectric tensor
     387                 :             : !!
     388                 :             : !! OUTPUT
     389                 :             : !!
     390                 :             : !! SOURCE
     391                 :             : 
     392                 :          17 : subroutine ddb_diel_elec(iout,epsinf)
     393                 :             : 
     394                 :             : !Arguments -------------------------------
     395                 :             : !scalars
     396                 :             :  integer,intent(in) :: iout
     397                 :             : !arrays
     398                 :             :  real(dp),intent(in) :: epsinf(3,3)
     399                 :             : 
     400                 :             : !Local variables -------------------------
     401                 :             : !scalars
     402                 :             :  integer :: idir1,idir2
     403                 :             :  character(len=500) :: message
     404                 :             : !arrays
     405                 :             : 
     406                 :          17 :  write(message, '(a,a)' ) ch10,' Electronic dielectric tensor'
     407                 :          17 :  call wrtout(std_out,message,'COLL')
     408                 :          17 :  call wrtout(iout,message,'COLL')
     409                 :             : 
     410                 :             :  !Compute the electronic contribution to the dielectric tensor
     411                 :             :  !Needs only the perturbations with E-field from the DDB
     412         [ +  + ]:          68 :  do idir1=1,3
     413                 :             : !   do idir2=1,3
     414                 :             : !     epsinf(idir1,idir2)=d2cart(1,idir1,natom+2,idir2,natom+2)
     415                 :             : !   end do
     416                 :          51 :    write(message, '(3f16.8)' )(epsinf(idir1,idir2),idir2=1,3)
     417                 :          51 :    call wrtout(std_out,message,'COLL')
     418                 :          68 :    call wrtout(iout,message,'COLL')
     419                 :             :  end do
     420                 :          17 :  call wrtout(iout, " ",'COLL')
     421                 :          17 :  call wrtout(std_out, " ",'COLL')
     422                 :             : 
     423                 :          17 : end subroutine ddb_diel_elec
     424                 :             : !!***
     425                 :             : 
     426                 :             : 
     427                 :             : 
     428                 :             : !!****f* ABINIT/ddb_oscstr
     429                 :             : !!
     430                 :             : !! NAME
     431                 :             : !! ddb_oscstr
     432                 :             : !!
     433                 :             : !! FUNCTION
     434                 :             : !! Compute the oscillator strength and the mode effective charge
     435                 :             : !!
     436                 :             : !! INPUTS
     437                 :             : !! displ(2,3*natom,3*natom)=
     438                 :             : !!  the displacements of atoms in cartesian coordinates.
     439                 :             : !!  The first index means either the real or the imaginary part,
     440                 :             : !!  The second index runs on the direction and the atoms displaced
     441                 :             : !!  The third index runs on the modes.
     442                 :             : !! d2cart(2,3,mpert,3,mpert)=
     443                 :             : !!  dynamical matrix, effective charges, dielectric tensor,....
     444                 :             : !!  all in cartesian coordinates
     445                 :             : !! iout=unit number for outputs
     446                 :             : !! mpert =maximum number of ipert
     447                 :             : !! natom=number of atoms in unit cell
     448                 :             : !! phfrq(3*natom)=phonon frequencies (square root of the dynamical
     449                 :             : !!  matrix eigenvalues, except if these are negative, and in this
     450                 :             : !!  case, give minus the square root of the absolute value
     451                 :             : !!  of the matrix eigenvalues). Hartree units.
     452                 :             : !!
     453                 :             : !! OUTPUT
     454                 :             : !! fact_oscstr(2,3,3*natom)=oscillator strengths for the different eigenmodes,
     455                 :             : !!  for different direction of the electric field.
     456                 :             : !! modez(2,3,3*natom)=mode effective charges for the different eigenmodes,
     457                 :             : !!  for different directions of the electric field, following
     458                 :             : !!  the definition Eq.(53) in PRB55, 10355 (1997) [[cite:Gonze1997a]]
     459                 :             : !! oscstr(2,3,3,3*natom)=oscillator strengths, following
     460                 :             : !!  the definition Eq.(54) in PRB55, 10355 (1997) [[cite:Gonze1997a]]
     461                 :             : !!
     462                 :             : !! SOURCE
     463                 :             : 
     464                 :          10 : subroutine ddb_oscstr(displ,d2cart,fact_oscstr,oscstr,modez,iout,mpert,natom,phfrq,ncid,my_rank)
     465                 :             : 
     466                 :             : !Arguments -------------------------------
     467                 :             : !scalars
     468                 :             :  integer,intent(in) :: iout,mpert,natom,ncid,my_rank
     469                 :             : !arrays
     470                 :             :  real(dp),intent(in) :: d2cart(2,3,mpert,3,mpert)
     471                 :             :  real(dp),intent(in) :: phfrq(3*natom)
     472                 :             :  real(dp),intent(inout) :: displ(2,3*natom,3*natom)
     473                 :             :  real(dp),intent(out) :: fact_oscstr(2,3,3*natom),oscstr(2,3,3,3*natom),modez(2,3,3*natom)
     474                 :             : 
     475                 :             : !Local variables -------------------------
     476                 :             : !scalars
     477                 :             :  integer,parameter :: master=0
     478                 :             :  integer :: i1,idir1,idir2,imode,ipert1
     479                 :             :  integer :: ncerr
     480                 :             :  real(dp) :: usquare
     481                 :             :  logical :: t_degenerate
     482                 :             : !arrays
     483                 :          10 :  character(len=1),allocatable :: metacharacter(:)
     484                 :             : 
     485                 :             : ! *********************************************************************
     486                 :             : 
     487                 :             : !  Get the factors of the oscillator strength, and the mode effective charge for each mode
     488         [ +  + ]:         163 :    do imode=1,3*natom
     489                 :             :      usquare=zero
     490         [ +  + ]:        3438 :      do i1=1,3*natom
     491                 :        3438 :        usquare=usquare+displ(1,i1,imode)*displ(1,i1,imode)+displ(2,i1,imode)*displ(2,i1,imode)
     492                 :             :      end do
     493         [ +  + ]:         622 :      do idir2=1,3
     494         [ +  + ]:        1377 :        fact_oscstr(:,idir2,imode)=zero
     495         [ +  + ]:        1377 :        modez(:,idir2,imode)=zero
     496         [ +  + ]:        1989 :        do idir1=1,3
     497         [ +  + ]:       11691 :          do ipert1=1,natom
     498                 :        9855 :            i1=idir1+(ipert1-1)*3
     499                 :             :            fact_oscstr(:,idir2,imode)=fact_oscstr(:,idir2,imode)+&
     500         [ +  + ]:       29565 : &           displ(:,i1,imode)*d2cart(1,idir1,ipert1,idir2,natom+2)
     501                 :             :            modez(:,idir2,imode)=modez(:,idir2,imode)+&
     502                 :             : &           displ(:,i1,imode)*&
     503         [ +  + ]:       30942 : &           d2cart(1,idir1,ipert1,idir2,natom+2)/sqrt(usquare)
     504                 :             :          end do
     505                 :             :        end do
     506                 :             :      end do
     507                 :             :    end do
     508                 :             : 
     509                 :             : !  Examine the degeneracy of each mode. The portability of the echo of the mode effective
     510                 :             : !  charges and oscillator strengths is very hard to guarantee. On the contrary,
     511                 :             : !  the scalar reductions of these quantities are OK.
     512   [ +  -  -  +  :          40 :    ABI_MALLOC(metacharacter,(3*natom))
          +  -  +  -  -  
                +  -  + ]
     513         [ +  + ]:         163 :    do imode=1,3*natom
     514                 :             : !    The degenerate modes are not portable
     515                 :         153 :      t_degenerate=.false.
     516         [ +  + ]:         153 :      if(imode>1)then
     517         [ +  + ]:         143 :        if(phfrq(imode)-phfrq(imode-1)<tol6)t_degenerate=.true.
     518                 :             :      end if
     519         [ +  + ]:         153 :      if(imode<3*natom)then
     520         [ +  + ]:         143 :        if(phfrq(imode+1)-phfrq(imode)<tol6)t_degenerate=.true.
     521                 :             :      end if
     522                 :         153 :      metacharacter(imode)=';'
     523         [ +  + ]:         163 :      if(t_degenerate)metacharacter(imode)='-'
     524                 :             :    end do
     525                 :             : 
     526         [ +  - ]:          10 :    if (my_rank == master) then
     527                 :             :      !  Write the mode effective charge for each mode
     528                 :          10 :      write(iout, '(a)' )'  '
     529                 :          10 :      write(iout, '(a)' )' Mode effective charges '
     530                 :          10 :      write(iout, '(a)' )' Mode number.    x            y            z            length '
     531         [ +  + ]:         163 :      do imode=1,3*natom
     532                 :         153 :        write(iout, '(a,i6,a,4f13.6)' )metacharacter(imode),imode,'     ',(modez(1,idir1,imode),idir1=1,3),&
     533                 :         316 : &                                   (sqrt(modez(1,1,imode)**2+modez(1,2,imode)**2+modez(1,3,imode)**2))
     534                 :             :      end do
     535                 :             :    end if ! master
     536                 :             : 
     537                 :             : !  Get the oscillator strengths
     538         [ +  + ]:         163 :    do imode=1,3*natom
     539         [ +  + ]:         622 :      do idir1=1,3
     540         [ +  + ]:        1989 :        do idir2=1,3
     541                 :             :          oscstr(1,idir1,idir2,imode)= &
     542                 :             : &         fact_oscstr(1,idir1,imode)*fact_oscstr(1,idir2,imode) +&
     543                 :        1377 : &         fact_oscstr(2,idir1,imode)*fact_oscstr(2,idir2,imode)
     544         [ +  + ]:        1377 :          if(abs(oscstr(1,idir1,idir2,imode))<tol14)oscstr(1,idir1,idir2,imode)=zero
     545                 :             : 
     546                 :             : !DEBUG
     547                 :             : !         if(idir1==1 .and. idir2==2)then
     548                 :             : !           write(std_out,'(a,i4,a,5es16.6)')'imode=',imode,&
     549                 :             : !&           ' oscstr(1,idir1,idir2,imode), fact_oscstr(:,idir1,imode),fact_oscstr(:,idir2,imode)=',&
     550                 :             : !&            oscstr(1,idir1,idir2,imode), fact_oscstr(:,idir1,imode),fact_oscstr(:,idir2,imode)
     551                 :             : !         endif
     552                 :             : !ENDDEBUG
     553                 :             : 
     554                 :             :          oscstr(2,idir1,idir2,imode)= &
     555                 :             : &         fact_oscstr(1,idir1,imode)*fact_oscstr(2,idir2,imode) -&
     556                 :        1377 : &         fact_oscstr(2,idir1,imode)*fact_oscstr(1,idir2,imode)
     557         [ +  - ]:        1836 :          if(abs(oscstr(2,idir1,idir2,imode))<tol14)oscstr(2,idir1,idir2,imode)=zero
     558                 :             :        end do
     559                 :             :      end do
     560                 :             :    end do
     561                 :             : 
     562         [ +  - ]:          10 :    if (my_rank == master) then
     563                 :             :      !  Write the oscillator strength for each mode
     564                 :          10 :      write(iout, '(a)' )'  '
     565                 :          10 :      write(iout, '(a)' )' Oscillator strengths (in a.u. ; 1 a.u.=253.2638413 m3/s2). Set to zero if abs()<tol14.'
     566                 :          10 :      write(iout, '(a)' )' Mode number.       xx          yy          zz          xy          xz          yz          trace'
     567         [ +  + ]:         163 :      do imode=1,3*natom
     568                 :             :        write(iout, '(a,i4,a,7es12.4)' )&
     569         [ +  + ]:         765 : &       metacharacter(imode),imode,'     Real  ',(oscstr(1,idir1,idir1,imode),idir1=1,3),&
     570                 :         153 : &       oscstr(1,1,2,imode), oscstr(1,1,3,imode),oscstr(1,2,3,imode),&
     571         [ +  - ]:         918 : &       ((oscstr(1,1,1,imode)+oscstr(1,2,2,imode)+oscstr(1,3,3,imode)))
     572                 :             :        write(iout, '(a,a,6es12.4)' )&
     573         [ +  + ]:         765 : &       metacharacter(imode),'         Imag  ',(oscstr(2,idir1,idir1,imode),idir1=1,3),&
     574         [ +  - ]:         928 : &       oscstr(2,1,2,imode),oscstr(2,1,3,imode),oscstr(2,2,3,imode)
     575                 :             :      end do
     576                 :             : 
     577                 :             :      ! write the oscillator strength to the netcdf
     578         [ +  - ]:          10 :      if (ncid /= nctk_noid) then
     579                 :             :        ncerr = nctk_def_arrays(ncid, [nctkarr_t("oscillator_strength", "dp", &
     580                 :             :        "complex, number_of_cartesian_directions, number_of_cartesian_directions, number_of_phonon_modes")], &
     581         [ +  + ]:          20 :        defmode=.True.)
     582         [ -  + ]:          10 :        NCF_CHECK(ncerr)
     583         [ -  + ]:          10 :        NCF_CHECK(nctk_set_datamode(ncid))
     584         [ -  + ]:          10 :        NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "oscillator_strength"), oscstr))
     585                 :             :      end if
     586                 :             :    end if
     587                 :             : 
     588         [ -  + ]:          10 :    ABI_FREE(metacharacter)
     589                 :             : 
     590                 :          10 : end subroutine ddb_oscstr
     591                 :             : !!***
     592                 :             : 
     593                 :             : 
     594                 :             : 
     595                 :             : !!****f* ABINIT/alignph
     596                 :             : !!
     597                 :             : !! NAME
     598                 :             : !! alignph
     599                 :             : !!
     600                 :             : !! FUNCTION
     601                 :             : !! Construct linear combinations of the phonon eigendisplacements
     602                 :             : !! of degenerate modes in order to align the mode effective charges
     603                 :             : !! along the axes of the cartesian frame.
     604                 :             : !!
     605                 :             : !! INPUTS
     606                 :             : !! amu(ntypat)=mass of the atoms (atomic mass unit)
     607                 :             : !! displ(2,3*natom,3*natom)=
     608                 :             : !! the displacements of atoms in cartesian coordinates.
     609                 :             : !! The first index means either the real or the imaginary part,
     610                 :             : !! The second index runs on the direction and the atoms displaced
     611                 :             : !! The third index runs on the modes.
     612                 :             : !! d2cart(2,3,mpert,3,mpert)=
     613                 :             : !!  dynamical matrix, effective charges, dielectric tensor,....
     614                 :             : !!  all in cartesian coordinates
     615                 :             : !! mpert =maximum number of ipert
     616                 :             : !! natom=number of atoms in unit cell
     617                 :             : !! ntypat=number of types of atoms
     618                 :             : !! phfrq(3*natom)=phonon frequencies (square root of the dynamical
     619                 :             : !!  matrix eigenvalues, except if these are negative, and in this
     620                 :             : !!  case, give minus the square root of the absolute value
     621                 :             : !!  of the matrix eigenvalues). Hartree units.
     622                 :             : !! typat(natom)=integer label of each type of atom (1,2,...)
     623                 :             : !!
     624                 :             : !! OUTPUT
     625                 :             : !! displ(2,3*natom,3*natom)=
     626                 :             : !!  the displacements of atoms in cartesian coordinates.
     627                 :             : !!  The eigendisplacements of degenerate modes have been aligned along
     628                 :             : !!  the cartesian axes.
     629                 :             : !!
     630                 :             : !! SOURCE
     631                 :             : 
     632                 :          33 : subroutine alignph(amu,displ,d2cart,mpert,natom,ntypat,phfrq,typat, &
     633                 :             :                    silent) !optional
     634                 :             : 
     635                 :             : !Arguments -------------------------------
     636                 :             : !scalars
     637                 :             :  integer,intent(in) :: mpert,natom,ntypat
     638                 :             :  integer,optional,intent(in) :: silent
     639                 :             : !arrays
     640                 :             :  integer,intent(in) :: typat(natom)
     641                 :             :  real(dp),intent(in) :: amu(ntypat),d2cart(2,3,mpert,3,mpert),phfrq(3*natom)
     642                 :             :  real(dp),intent(inout) :: displ(2,3*natom,3*natom)
     643                 :             : 
     644                 :             : !Local variables -------------------------
     645                 :             : !scalars
     646                 :             :  integer,parameter :: master=0
     647                 :             :  integer :: i1,idir1,idir2,ii,imode,imodex,imodey,imodez,ipert1,silent_
     648                 :             :  real(dp) :: theta
     649                 :             : !arrays
     650                 :          33 :  integer,allocatable :: deg(:)
     651                 :             :  real(dp) :: zvec(3,3),zvect(3,3)
     652                 :          33 :  real(dp),allocatable :: modez(:,:,:),modezabs(:),oscstr(:,:,:),vec(:,:),vect(:,:)
     653                 :             : 
     654                 :             : ! *********************************************************************
     655                 :             : 
     656                 :             : !Reduce verbosity
     657                 :          33 :  silent_=0
     658         [ +  + ]:          33 :  if (present(silent)) silent_=silent
     659                 :             : 
     660                 :             : !Get the oscillator strength and mode effective charge for each mode
     661   [ +  -  -  +  :         132 :  ABI_MALLOC(oscstr,(2,3,3*natom))
          +  -  +  -  +  
             -  -  +  -  
                      + ]
     662   [ -  +  +  -  :          66 :  ABI_MALLOC(modez,(2,3,3*natom))
             -  +  -  + ]
     663   [ -  +  +  -  :          99 :  ABI_MALLOC(modezabs,(3*natom))
          +  -  +  -  -  
                +  -  + ]
     664   [ -  +  +  -  :         132 :  ABI_MALLOC(vec,(3*natom,3))
          +  -  +  -  +  
             -  -  +  -  
                      + ]
     665   [ -  +  +  -  :          66 :  ABI_MALLOC(vect,(3*natom,3))
             -  +  -  + ]
     666   [ -  +  +  -  :          99 :  ABI_MALLOC(deg,(3*natom))
          +  -  +  -  -  
                +  -  + ]
     667                 :             : 
     668         [ +  + ]:          33 :  if (silent_/=1) then
     669                 :           3 :    write(std_out,'(a,a)')ch10,' alignph : before modifying the eigenvectors, mode number and mode effective charges :'
     670                 :             :  end if
     671         [ +  + ]:         591 :  do imode=1,3*natom
     672                 :         558 :    modezabs(imode)=zero
     673         [ +  + ]:        1674 :    do ii=1,2
     674         [ +  + ]:        5022 :      do idir2=1,3
     675                 :        3348 :        oscstr(ii,idir2,imode)=zero
     676                 :        3348 :        modez(ii,idir2,imode)=zero
     677         [ +  + ]:       13392 :        do idir1=1,3
     678         [ +  + ]:       72360 :          do ipert1=1,natom
     679                 :       58968 :            i1=idir1+(ipert1-1)*3
     680                 :             :            oscstr(ii,idir2,imode)=oscstr(ii,idir2,imode)+&
     681                 :             : &           displ(ii,i1,imode)*&
     682                 :       58968 : &           d2cart(1,idir1,ipert1,idir2,natom+2)
     683                 :             :            modez(ii,idir2,imode)=modez(ii,idir2,imode)+&
     684                 :             : &           displ(ii,i1,imode)*&
     685                 :             : &           d2cart(1,idir1,ipert1,idir2,natom+2)*&
     686                 :       69012 : &           sqrt(amu(typat(ipert1))*amu_emass)
     687                 :             :          end do
     688                 :             :        end do
     689         [ +  + ]:        4464 :        if(abs(modez(ii,idir2,imode))>modezabs(imode))modezabs(imode)=abs(modez(ii,idir2,imode))
     690                 :             :      end do
     691                 :             :    end do
     692         [ +  + ]:         591 :    if (silent_/=1) write(std_out,'(i4,3f16.6)')imode,modez(1,:,imode)
     693                 :             :  end do
     694                 :             : 
     695                 :             : !Find degenerate modes with non-zero mode effective charge
     696                 :          33 :  imode = 0
     697         [ +  + ]:         482 :  do while (imode < 3*natom)
     698                 :         449 :    imode = imode + 1
     699         [ +  + ]:         482 :    if (imode == 3*natom) then
     700                 :          10 :      deg(imode) = 1
     701   [ +  +  +  +  :         439 :    else if (abs(phfrq(imode) - phfrq(imode+1)) > tol6 .or. modezabs(imode)<tol8 .or. modezabs(imode+1)<tol8) then
                   -  + ]
     702                 :             : !    Differ by phonon frequency or zero mode effective charge
     703                 :         336 :      deg(imode) = 1
     704                 :             :    else
     705                 :         103 :      deg(imode) = 2
     706         [ +  + ]:         103 :      if (imode < 3*natom - 1) then
     707   [ +  +  +  - ]:          83 :        if (abs(phfrq(imode) - phfrq(imode+2)) < tol6 .and. modezabs(imode+2)>tol8) then
     708                 :           6 :          deg(imode) = 3
     709                 :           6 :          imode = imode + 1
     710                 :             :        end if
     711                 :             :      end if
     712                 :         103 :      imode = imode + 1
     713                 :             :    end if
     714                 :             :  end do
     715                 :             : 
     716                 :             : 
     717                 :             : !In case of a degenerate mode, with non-zero mode effective charge, align the mode effective charge vector along
     718                 :             : !the axes of the cartesian frame
     719                 :          33 :  imode = 1
     720         [ +  + ]:         482 :  do while (imode <= 3*natom)
     721                 :             : 
     722         [ +  + ]:         449 :    if (silent_/=1) then
     723                 :           6 :      write(std_out,'(a,a,i4,a,i2)')ch10,' Mode number ',imode,' has degeneracy ',deg(imode)
     724                 :           6 :      write(std_out,'(a,3es16.6)') ' Mode effective charge of this mode =',modez(1,:,imode)
     725                 :             :    end if
     726                 :             : 
     727         [ +  + ]:         449 :    if (deg(imode) == 2) then
     728                 :             : 
     729                 :             : !    Optimize on the x direction
     730         [ -  + ]:          97 :      if (silent_/=1) then
     731                 :           0 :        write(std_out,'(a,3es16.6)') ' Mode effective charge of next mode =',modez(1,:,imode+1)
     732                 :             :      end if
     733         [ +  + ]:          97 :      if (abs(modez(1,1,imode)) > tol8) then
     734                 :          95 :        theta = atan(-modez(1,1,imode+1)/modez(1,1,imode))
     735         [ +  + ]:        1805 :        vec(:,1) = displ(1,:,imode)
     736         [ +  + ]:        1805 :        vec(:,2) = displ(1,:,imode+1)
     737         [ +  + ]:        1805 :        displ(1,:,imode) = cos(theta)*vec(:,1) - sin(theta)*vec(:,2)
     738         [ +  + ]:        1805 :        displ(1,:,imode+1) = sin(theta)*vec(:,1) + cos(theta)*vec(:,2)
     739                 :             : 
     740                 :             : !      MR: Rotate also the imaginary part
     741         [ +  + ]:        1805 :        vec(:,1) = displ(2,:,imode)
     742         [ +  + ]:        1805 :        vec(:,2) = displ(2,:,imode+1)
     743         [ +  + ]:        1805 :        displ(2,:,imode) = cos(theta)*vec(:,1) - sin(theta)*vec(:,2)
     744         [ +  + ]:        1805 :        displ(2,:,imode+1) = sin(theta)*vec(:,1) + cos(theta)*vec(:,2)
     745                 :             : 
     746                 :             :      end if
     747                 :             : 
     748         [ +  + ]:         352 :    else if (deg(imode) == 3) then
     749                 :             : 
     750         [ +  - ]:           6 :      if (silent_/=1) then
     751                 :           6 :        write(std_out,'(a,3es16.6)') ' Mode effective charge of next mode =',modez(1,:,imode+1)
     752                 :           6 :        write(std_out,'(a,3es16.6)') ' Mode effective charge of next-next mode =',modez(1,:,imode+2)
     753                 :             :      end if
     754                 :             : 
     755                 :             : !    Before mixing them, select the mode-effective charge vectors as being predominently "x", "y" or "z" type.
     756         [ #  # ]:           0 :      if(abs(modez(1,1,imode))>abs(modez(1,2,imode))-tol12 .and. &
     757         [ -  + ]:           6 : &     abs(modez(1,1,imode))>abs(modez(1,3,imode))-tol12) then
     758                 :           0 :        imodex=imode
     759         [ #  # ]:           0 :        if(abs(modez(1,2,imode+1))>abs(modez(1,3,imode+1))-tol12)then
     760                 :           0 :          imodey=imode+1 ; imodez=imode+2
     761                 :             :        else
     762                 :           0 :          imodez=imode+1 ; imodey=imode+2
     763                 :             :        end if
     764         [ -  + ]:           6 :      else if(abs(modez(1,2,imode))>abs(modez(1,1,imode))-tol12 .and. &
     765         [ +  - ]:           6 : &       abs(modez(1,2,imode))>abs(modez(1,3,imode))-tol12) then
     766                 :           0 :        imodey=imode
     767         [ #  # ]:           0 :        if(abs(modez(1,1,imode+1))>abs(modez(1,3,imode+1))-tol12)then
     768                 :           0 :          imodex=imode+1 ; imodez=imode+2
     769                 :             :        else
     770                 :           0 :          imodez=imode+1 ; imodex=imode+2
     771                 :             :        end if
     772                 :             :      else
     773                 :           6 :        imodez=imode
     774         [ -  + ]:           6 :        if(abs(modez(1,1,imode+1))>abs(modez(1,2,imode+1))-tol12)then
     775                 :           0 :          imodex=imode+1 ; imodey=imode+2
     776                 :             :        else
     777                 :           6 :          imodey=imode+1 ; imodex=imode+2
     778                 :             :        end if
     779                 :             :      end if
     780         [ +  + ]:          42 :      vec(:,1)=displ(1,:,imodex)
     781         [ +  + ]:          42 :      vec(:,2)=displ(1,:,imodey)
     782         [ +  + ]:          42 :      vec(:,3)=displ(1,:,imodez)
     783         [ +  + ]:          24 :      zvec(:,1)=modez(1,:,imodex)
     784         [ +  + ]:          24 :      zvec(:,2)=modez(1,:,imodey)
     785         [ +  + ]:          24 :      zvec(:,3)=modez(1,:,imodez)
     786                 :             : 
     787                 :             : 
     788                 :             : !    Optimize along x : does the first vector has a component along x ?
     789         [ +  - ]:           6 :      if (abs(zvec(1,1)) > tol8) then
     790                 :             : !      Optimize on the (1,2) pair of modes along x
     791                 :           6 :        theta = atan(-zvec(1,2)/zvec(1,1))
     792                 :           6 :        zvect(:,:)=zvec(:,:)
     793         [ +  + ]:          24 :        zvec(:,1) = cos(theta)*zvect(:,1) - sin(theta)*zvect(:,2)
     794         [ +  + ]:          24 :        zvec(:,2) = sin(theta)*zvect(:,1) + cos(theta)*zvect(:,2)
     795   [ +  +  +  + ]:         132 :        vect(:,:)=vec(:,:)
     796         [ +  + ]:          42 :        vec(:,1) = cos(theta)*vect(:,1) - sin(theta)*vect(:,2)
     797         [ +  + ]:          42 :        vec(:,2) = sin(theta)*vect(:,1) + cos(theta)*vect(:,2)
     798                 :             : !      Optimize on the (1,3) pair of modes along x
     799                 :           6 :        theta = atan(-zvec(1,3)/zvec(1,1))
     800                 :           6 :        zvect(:,:)=zvec(:,:)
     801         [ +  + ]:          24 :        zvec(:,1) = cos(theta)*zvect(:,1) - sin(theta)*zvect(:,3)
     802         [ +  + ]:          24 :        zvec(:,3) = sin(theta)*zvect(:,1) + cos(theta)*zvect(:,3)
     803   [ +  +  +  + ]:         132 :        vect(:,:)=vec(:,:)
     804         [ +  + ]:          42 :        vec(:,1) = cos(theta)*vect(:,1) - sin(theta)*vect(:,3)
     805         [ +  + ]:          42 :        vec(:,3) = sin(theta)*vect(:,1) + cos(theta)*vect(:,3)
     806         [ +  - ]:           6 :        if (abs(zvec(2,2)) > tol8) then
     807                 :             : !        Optimize on the (2,3) pair of modes along y
     808                 :           6 :          theta = atan(-zvec(2,3)/zvec(2,2))
     809                 :           6 :          zvect(:,:)=zvec(:,:)
     810         [ +  + ]:          24 :          zvec(:,2) = cos(theta)*zvect(:,2) - sin(theta)*zvect(:,3)
     811         [ +  + ]:          24 :          zvec(:,3) = sin(theta)*zvect(:,2) + cos(theta)*zvect(:,3)
     812   [ +  +  +  + ]:         132 :          vect(:,:)=vec(:,:)
     813         [ +  + ]:          42 :          vec(:,2) = cos(theta)*vect(:,2) - sin(theta)*vect(:,3)
     814         [ +  + ]:          42 :          vec(:,3) = sin(theta)*vect(:,2) + cos(theta)*vect(:,3)
     815                 :             :        end if
     816                 :             : !    Likely, the remaining is not needed ... because the vectors have been ordered in x, y, and z major component ...
     817                 :             : !    Optimize along x : does the second vector has a component along x ?
     818         [ #  # ]:           0 :      else if(abs(zvec(1,2)) > tol8) then
     819                 :             : !      Optimize on the (2,3) pair of modes along x
     820                 :           0 :        theta = atan(-zvec(1,3)/zvec(1,2))
     821                 :           0 :        zvect(:,:)=zvec(:,:)
     822         [ #  # ]:           0 :        zvec(:,2) = cos(theta)*zvect(:,2) - sin(theta)*zvect(:,3)
     823         [ #  # ]:           0 :        zvec(:,3) = sin(theta)*zvect(:,2) + cos(theta)*zvect(:,3)
     824   [ #  #  #  # ]:           0 :        vect(:,:)=vec(:,:)
     825         [ #  # ]:           0 :        vec(:,2) = cos(theta)*vect(:,2) - sin(theta)*vect(:,3)
     826         [ #  # ]:           0 :        vec(:,3) = sin(theta)*vect(:,2) + cos(theta)*vect(:,3)
     827                 :             : !      Optimize on the (1,3) pair of modes along y
     828         [ #  # ]:           0 :        if (abs(zvec(2,1)) > tol8) then
     829                 :           0 :          theta = atan(-zvec(2,3)/zvec(2,1))
     830                 :           0 :          zvect(:,:)=zvec(:,:)
     831         [ #  # ]:           0 :          zvec(:,1) = cos(theta)*zvect(:,1) - sin(theta)*zvect(:,3)
     832         [ #  # ]:           0 :          zvec(:,3) = sin(theta)*zvect(:,1) + cos(theta)*zvect(:,3)
     833   [ #  #  #  # ]:           0 :          vect(:,:)=vec(:,:)
     834         [ #  # ]:           0 :          vec(:,1) = cos(theta)*vect(:,1) - sin(theta)*vect(:,3)
     835         [ #  # ]:           0 :          vec(:,3) = sin(theta)*vect(:,1) + cos(theta)*vect(:,3)
     836                 :             :        end if
     837                 :             : !    We are left with the pair of vectors (2,3)
     838         [ #  # ]:           0 :      else if (abs(zvec(2,2)) > tol8) then
     839                 :             : !      Optimize on the (2,3) pair of modes along y
     840                 :           0 :        theta = atan(-zvec(2,3)/zvec(2,2))
     841                 :           0 :        zvect(:,:)=zvec(:,:)
     842         [ #  # ]:           0 :        zvec(:,2) = cos(theta)*zvect(:,2) - sin(theta)*zvect(:,3)
     843         [ #  # ]:           0 :        zvec(:,3) = sin(theta)*zvect(:,2) + cos(theta)*zvect(:,3)
     844   [ #  #  #  # ]:           0 :        vect(:,:)=vec(:,:)
     845         [ #  # ]:           0 :        vec(:,2) = cos(theta)*vect(:,2) - sin(theta)*vect(:,3)
     846         [ #  # ]:           0 :        vec(:,3) = sin(theta)*vect(:,2) + cos(theta)*vect(:,3)
     847                 :             :      end if
     848                 :             : 
     849         [ +  + ]:          42 :      displ(1,:,imodex)=vec(:,1)
     850         [ +  + ]:          42 :      displ(1,:,imodey)=vec(:,2)
     851         [ +  + ]:          42 :      displ(1,:,imodez)=vec(:,3)
     852                 :             : 
     853                 :             : !    Previous coding, from Marek. Apparently, break the orthogonalization of vectors ...
     854                 :             : !    do ii = 1,3
     855                 :             : !      coeff(:) = 0._dp
     856                 :             : !      if (ii == 1) then
     857                 :             : !        jj = 2 ; kk = 3
     858                 :             : !      else if (ii == 2) then
     859                 :             : !        jj = 1 ; kk = 3
     860                 :             : !      else
     861                 :             : !        jj = 1 ; kk = 2
     862                 :             : !      end if
     863                 :             : !      coeff(ii) = 1._dp
     864                 :             : !      c1 = modez(1,jj,imode+ii-1)
     865                 :             : !      c2 = modez(1,jj,imode+jj-1)
     866                 :             : !      c3 = modez(1,jj,imode+kk-1)
     867                 :             : !      c4 = modez(1,kk,imode+ii-1)
     868                 :             : !      c5 = modez(1,kk,imode+jj-1)
     869                 :             : !      c6 = modez(1,kk,imode+kk-1)
     870                 :             : !      dtm = c2*c6 - c3*c5
     871                 :             : !      if (abs(dtm) > tol8) then
     872                 :             : !        coeff(jj) = (c3*c4 - c1*c6)/dtm
     873                 :             : !        coeff(kk) = (c1*c5 - c2*c4)/dtm
     874                 :             : !      end if
     875                 :             : !      mod_ = sqrt(1._dp + coeff(jj)*coeff(jj) + coeff(kk)*coeff(kk))
     876                 :             : !      coeff(:) = coeff(:)/mod_
     877                 :             : !      displ(1,:,imode+ii-1) = coeff(1)*vec(1,:) + coeff(2)*vec(2,:) + &
     878                 :             : !&       coeff(3)*vec(3,:)
     879                 :             : !    end do
     880                 :             : 
     881                 :             :    end if ! if deg mode
     882                 :             : 
     883                 :         449 :    imode = imode + deg(imode)
     884                 :             : 
     885                 :             :  end do
     886                 :             : 
     887         [ +  + ]:          33 :  if (silent_/=1) then
     888                 :           3 :    write(std_out,'(a,a)')ch10,' alignph : after modifying the eigenvectors, mode number and mode effective charges :'
     889                 :             :  end if
     890         [ +  + ]:         591 :  do imode=1,3*natom
     891         [ +  + ]:        1674 :    do ii=1,2
     892         [ +  + ]:        5022 :      do idir2=1,3
     893                 :        3348 :        modez(ii,idir2,imode)=zero
     894         [ +  + ]:       14508 :        do idir1=1,3
     895         [ +  + ]:       72360 :          do ipert1=1,natom
     896                 :       58968 :            i1=idir1+(ipert1-1)*3
     897                 :             :            modez(ii,idir2,imode)=modez(ii,idir2,imode)+&
     898                 :             : &           displ(ii,i1,imode)*&
     899                 :             : &           d2cart(1,idir1,ipert1,idir2,natom+2)*&
     900                 :       69012 : &           sqrt(amu(typat(ipert1))*amu_emass)
     901                 :             :          end do
     902                 :             :        end do
     903                 :             :      end do
     904                 :             :    end do
     905         [ +  + ]:         591 :    if (silent_/=1)  write(std_out,'(i4,3f16.6)')imode,modez(1,:,imode)
     906                 :             :  end do
     907                 :             : 
     908         [ -  + ]:          33 :  ABI_FREE(deg)
     909         [ -  + ]:          33 :  ABI_FREE(oscstr)
     910         [ -  + ]:          33 :  ABI_FREE(modez)
     911         [ -  + ]:          33 :  ABI_FREE(modezabs)
     912         [ -  + ]:          33 :  ABI_FREE(vec)
     913         [ -  + ]:          33 :  ABI_FREE(vect)
     914                 :             : 
     915                 :          33 : end subroutine alignph
     916                 :             : !!***
     917                 :             : 
     918                 :             : end module m_ddb_diel
     919                 :             : !!***
        

Generated by: LCOV version 2.3-1