LCOV - code coverage report
Current view: top level - src/44_abitools - m_dynmat.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 88.3 % 2158 1905
Test Date: 2026-11-11 11:17:02 Functions: 93.5 % 46 43
Branches: 73.1 % 3679 2688

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_dynmat
       2                 :             : !! NAME
       3                 :             : !!  m_dynmat
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !!  This module provides low-level tools to operate on the dynamical matrix
       7                 :             : !!
       8                 :             : !! COPYRIGHT
       9                 :             : !!  Copyright (C) 2014-2026 ABINIT group (XG, JCC, MJV, NH, RC, MVeithen, MM, MG, MT, DCA)
      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                 :             : !! TODO
      15                 :             : !!  Use more explicative names for the procedures!
      16                 :             : !!
      17                 :             : !! SOURCE
      18                 :             : 
      19                 :             : #if defined HAVE_CONFIG_H
      20                 :             : #include "config.h"
      21                 :             : #endif
      22                 :             : 
      23                 :             : #include "abi_common.h"
      24                 :             : 
      25                 :             : module m_dynmat
      26                 :             : 
      27                 :             :  use, intrinsic :: iso_c_binding
      28                 :             :  use defs_basis
      29                 :             :  use m_abicore
      30                 :             :  use m_errors
      31                 :             :  use m_linalg_interfaces
      32                 :             :  use m_xmpi
      33                 :             : 
      34                 :             :  use m_fstrings,        only : itoa, sjoin
      35                 :             :  use m_numeric_tools,   only : wrap2_pmhalf, mkherm
      36                 :             :  use m_matrix,          only : mati3inv, matr3inv
      37                 :             :  use m_symtk,           only : littlegroup_q
      38                 :             :  use m_cgtools,         only : fxphas_seq
      39                 :             :  use m_crystal,        only : crystal_t
      40                 :             :  use m_ewald,           only : ewald9, ewald9_2D
      41                 :             :  use m_time,            only : timab
      42                 :             : 
      43                 :             :  implicit none
      44                 :             : 
      45                 :             :  private
      46                 :             : 
      47                 :             :  public :: asria_calc           ! Calculate the correction for the Acoustic sum rule on
      48                 :             :                                 !   the InterAtomic Forces or on the dynamical matrix directly
      49                 :             :  public :: asria_corr           ! Imposition of the Acoustic sum rule on the InterAtomic Forces
      50                 :             :                                 !   or on the dynamical matrix directly from the previously calculated d2asr
      51                 :             :  public :: asrprs               ! Imposition of the Acoustic sum rule on the InterAtomic Forces Plus Rotational Symmetry
      52                 :             :  public :: cart29               ! Transform a second-derivative matrix from reduced  coordinates to cartesian coordinates, and also
      53                 :             :                                 !   1) add the ionic part of the effective charges,
      54                 :             :                                 !   2) normalize the electronic dielectric tensor, and add the vacuum polarisation
      55                 :             :  public :: cart39               ! Transform a vector from reduced coordinates to cartesian coordinates,
      56                 :             :                                 !   taking into account the perturbation from which it was derived,
      57                 :             :                                 !   and also check the existence of the new values.
      58                 :             :  public :: d2cart_to_red        ! Transform a second-derivative matrix
      59                 :             :                                 ! from cartesian to reduced coordinate.
      60                 :             :  public :: chkph3               ! Check the completeness of the dynamical matrix
      61                 :             :  public :: chneu9               ! Imposition of the charge neutrality sum rule on the Effective charges
      62                 :             :  public :: d2sym3               ! Build (nearly) all the other matrix elements that can be build using symmetries.
      63                 :             :  public :: q0dy3_apply          ! Takes care of the inclusion of the ewald q=0 term in the dynamical matrix
      64                 :             :  public :: q0dy3_calc           ! Calculate the q=0 correction term to the dynamical matrix
      65                 :             :  ! TODO: 3 routines to symmetrize. Clarify different use cases
      66                 :             :  public :: symdyma              ! Symmetrize the dynamical matrices
      67                 :             :  public :: dfpt_sygra           ! Symmetrize derivatives of energy with respect to coordinates,
      68                 :             :  public :: dfpt_sydy            ! Symmetrize dynamical matrix (eventually diagonal wrt to the atoms)
      69                 :             :  public :: wings3               ! Suppress the wings of the cartesian 2DTE for which the diagonal element is not known
      70                 :             :  public :: asrif9               ! Imposes the Acoustic Sum Rule to Interatomic Forces
      71                 :             :  public :: get_bigbox_and_weights ! Compute
      72                 :             :  public :: bigbx9               ! Generates a Big Box of R points for the Fourier Transforms the dynamical matrix
      73                 :             :  public :: make_bigbox          ! Helper functions that faciliates the generation  of a Big Box containing
      74                 :             :  public :: canat9               ! From reduced to canonical coordinates
      75                 :             :  public :: canct9               ! Convert from canonical coordinates to cartesian coordinates
      76                 :             :  public :: chkrp9               ! Check if the rprim used for the definition of the unit cell (in the
      77                 :             :                                 ! inputs) are consistent with the rprim used in the routine generating  the Big Box
      78                 :             :  public :: dist9                ! Compute the distance between atoms in the big box
      79                 :             :  public :: ftifc_q2r            ! Fourier transform of the dynamical matrices to obtain interatomic forces (real space).
      80                 :             :  public :: ftifc_r2q            ! Fourier transform of the interatomic forces to obtain dynamical matrices (reciprocal space).
      81                 :             :  public :: dynmat_dq            ! Compute the derivative D(q)/dq via Fourier transform of the interatomic forces
      82                 :             :  public :: ifclo9               ! Convert from cartesian coordinates to local coordinates
      83                 :             :  public :: wght9                ! Generates a weight to each R points of the Big Box and for each pair of atoms
      84                 :             :  public :: d3sym                ! Given a set of calculated elements of the 3DTE matrix,
      85                 :             :                                 ! build (nearly) all the other matrix elements that can be build using symmetries.
      86                 :             :  public :: sytens               ! Determines the set of irreductible elements of the nonlinear optical susceptibility
      87                 :             :                                 ! and Raman tensors
      88                 :             :  public :: axial9               ! Generates the local coordinates system from the  knowledge of the first vector (longitudinal) and
      89                 :             :                                 !   the ifc matrix in cartesian coordinates
      90                 :             :  public :: dymfz9               ! Multiply the dynamical matrix by a phase shift to account for normalized canonical coordinates.
      91                 :             :  public :: nanal9               ! Subtract/Add the non-analytical part from one dynamical matrix with number iqpt.
      92                 :             :  public :: gtdyn9               ! Generates a dynamical matrix from interatomic force constants and
      93                 :             :                                 ! long-range electrostatic interactions.
      94                 :             :  public :: dfpt_phfrq           ! Diagonalize IFC(q), return phonon frequencies and eigenvectors.
      95                 :             :                                 ! If q is Gamma, the non-analytical behaviour can be included.
      96                 :             :  public :: pheigvec_normalize   ! Normalize input eigenvectors in cartesian coordinates.
      97                 :             :  public :: phdispl_from_eigvec  ! Phonon displacements from eigenvectors
      98                 :             :  public :: phangmom_from_eigvec ! compute phonon angular momentum for one q-point from eigenvectors
      99                 :             :  public :: dfpt_prtph           ! Print phonon frequencies
     100                 :             :  public :: massmult_and_breaksym  ! Multiply IFC(q) by atomic masses.
     101                 :             :  public :: massmult_and_breaksym_cplx  ! Version for complex array
     102                 :             : 
     103                 :             :  ! TODO: Change name,
     104                 :             :  public :: ftgam
     105                 :             :  public :: ftgam_init
     106                 :             : 
     107                 :             :  public :: msria_calc          ! Calculate the correction for the Acoustic sum rule
     108                 :             :                                ! + rotational invariance on the IFCs in reciprocal space
     109                 :             :  public :: msria_apply         ! Apply the correction for the Acoustic sum rule + rotational invariance
     110                 :             :                                ! If IFCs derivatives calculated both from LW driver and Fourier, correct the interpolation
     111                 :             : 
     112                 :             : ! *************************************************************************
     113                 :             : 
     114                 :             : contains
     115                 :             : !!***
     116                 :             : 
     117                 :             : !!****f* m_dynmat/asria_calc
     118                 :             : !! NAME
     119                 :             : !! asria_calc
     120                 :             : !!
     121                 :             : !! FUNCTION
     122                 :             : !! Calculate the correction for the Acoustic sum rule on the InterAtomic Forces
     123                 :             : !! or on the dynamical matrix directly
     124                 :             : !!
     125                 :             : !! INPUTS
     126                 :             : !! asr=(0 => no ASR, 1 or 2=> the diagonal element is modified to give the ASR,
     127                 :             : !!      5 => impose hermitian solution using lapack call)
     128                 :             : !! d2cart=matrix of second derivatives of total energy, in cartesian coordinates
     129                 :             : !! mpert =maximum number of ipert
     130                 :             : !! natom=number of atom
     131                 :             : !!
     132                 :             : !! OUTPUT
     133                 :             : !! d2asr=matrix used to store the correction needed to fulfill
     134                 :             : !! the acoustic sum rule.
     135                 :             : !!
     136                 :             : !! SOURCE
     137                 :             : 
     138                 :         286 : subroutine asria_calc(asr,d2asr,d2cart,mpert,natom)
     139                 :             : 
     140                 :             : !Arguments -------------------------------
     141                 :             : !scalars
     142                 :             :  integer,intent(in) :: asr,mpert,natom
     143                 :             : !arrays
     144                 :             :  real(dp),intent(in) :: d2cart(2,3,mpert,3,mpert)
     145                 :             :  real(dp),intent(out) :: d2asr(2,3,natom,3,natom)
     146                 :             : 
     147                 :             : !Local variables-------------------------------
     148                 :             : !scalars
     149                 :             :  integer :: idir1,idir2,ii,ipert1,ipert2
     150                 :             :  integer :: constrank, imatelem, iconst, nconst, nd2_packed, info
     151                 :             :  !character(len=500) :: msg
     152                 :             : !arrays
     153                 :         286 :  integer, allocatable :: packingindex(:,:,:,:)
     154                 :         286 :  real(dp), allocatable :: constraints(:,:,:)
     155                 :         286 :  real(dp), allocatable :: d2cart_packed(:,:)
     156                 :         286 :  real(dp), allocatable :: singvals(:)
     157                 :         286 :  real(dp), allocatable :: constr_rhs(:,:)
     158                 :         286 :  real(dp), allocatable :: work(:,:),rwork(:)
     159                 :             : ! *********************************************************************
     160                 :             : 
     161   [ +  +  +  +  :      127546 :  d2asr = zero
          +  +  +  +  +  
                      + ]
     162                 :             : 
     163         [ +  - ]:         286 :  if (asr==0) return
     164                 :             : 
     165                 :             :  !call wrtout(std_out,' asria_calc: calculation of the correction to the ASR for the interatomic forces.')
     166         [ +  + ]:        1156 :  do ipert1=1,natom
     167         [ +  + ]:        3766 :    do idir1=1,3
     168         [ +  + ]:       11310 :      do idir2=1,3
     169                 :             : 
     170                 :             : !      Compute d2asr
     171         [ +  + ]:       47574 :        do ipert2=1,natom
     172                 :             :          d2asr(:,idir1,ipert1,idir2,ipert1)=&
     173                 :             : &         d2asr(:,idir1,ipert1,idir2,ipert1)+&
     174         [ +  + ]:      119232 : &         d2cart(:,idir1,ipert1,idir2,ipert2)
     175                 :             :        end do
     176                 :             :      end do
     177                 :             :    end do
     178                 :             :  end do
     179                 :             : 
     180                 :             : !holistic method: overwrite d2asr with hermitian solution
     181         [ -  + ]:         286 :  if (asr == 5) then
     182                 :           0 :    nconst = 9*natom
     183                 :           0 :    nd2_packed = 3*natom*(3*natom+1)/2
     184   [ #  #  #  #  :           0 :    ABI_MALLOC(constraints,(2,nconst, nd2_packed))
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     185   [ #  #  #  #  :           0 :    ABI_MALLOC(d2cart_packed,(2,nd2_packed))
          #  #  #  #  #  
                #  #  # ]
     186   [ #  #  #  #  :           0 :    ABI_MALLOC(constr_rhs,(2,nd2_packed))
             #  #  #  # ]
     187   [ #  #  #  #  :           0 :    ABI_MALLOC(singvals,(nconst))
          #  #  #  #  #  
                #  #  # ]
     188   [ #  #  #  #  :           0 :    ABI_MALLOC(work,(2,3*nd2_packed))
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     189   [ #  #  #  #  :           0 :    ABI_MALLOC(rwork,(5*nd2_packed))
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     190   [ #  #  #  #  :           0 :    ABI_MALLOC(packingindex,(3,natom,3,natom))
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     191                 :           0 :    ii=1
     192   [ #  #  #  #  :           0 :    packingindex=-1
             #  #  #  # ]
     193         [ #  # ]:           0 :    do ipert2=1,natom
     194         [ #  # ]:           0 :      do idir2=1,3
     195         [ #  # ]:           0 :        do ipert1=1,ipert2-1
     196         [ #  # ]:           0 :          do idir1=1,3
     197                 :           0 :            packingindex(idir1,ipert1,idir2,ipert2) = ii
     198                 :           0 :            ii = ii+1
     199                 :             :          end do
     200                 :             :        end do
     201         [ #  # ]:           0 :        do idir1=1,idir2
     202                 :           0 :          packingindex(idir1,ipert2,idir2,ipert2) = ii
     203                 :           0 :          ii = ii+1
     204                 :             :        end do
     205                 :             :      end do
     206                 :             :    end do
     207                 :             : !  setup constraint matrix
     208   [ #  #  #  #  :           0 :    constraints = zero
                   #  # ]
     209         [ #  # ]:           0 :    do ipert1=1,natom
     210         [ #  # ]:           0 :      do idir1=1,3
     211         [ #  # ]:           0 :        do idir2=1,3
     212                 :           0 :          iconst = idir2+3*(idir1-1 + 3*(ipert1-1))
     213                 :             : !        set all atom forces, this component
     214         [ #  # ]:           0 :          do ipert2=1,natom
     215                 :           0 :            imatelem = packingindex(idir1,ipert1,idir2,ipert2)
     216         [ #  # ]:           0 :            if (imatelem == -1) then
     217                 :           0 :              imatelem = packingindex(idir2,ipert2,idir1,ipert1)
     218                 :             :            end if
     219                 :           0 :            constraints(1,iconst,imatelem) = one
     220                 :             :          end do
     221                 :             :        end do
     222                 :             :      end do
     223                 :             :    end do
     224                 :             : 
     225   [ #  #  #  # ]:           0 :    d2cart_packed = -999.0d0
     226         [ #  # ]:           0 :    do ipert2=1,natom
     227         [ #  # ]:           0 :      do idir2=1,3
     228         [ #  # ]:           0 :        do ipert1=1,natom
     229         [ #  # ]:           0 :          do idir1=1,3
     230                 :           0 :            imatelem = packingindex(idir1,ipert1,idir2,ipert2)
     231         [ #  # ]:           0 :            if (imatelem == -1) cycle
     232         [ #  # ]:           0 :            d2cart_packed(:,imatelem) = d2cart(:,idir1,ipert1,idir2,ipert2)
     233                 :             :          end do
     234                 :             :        end do
     235                 :             :      end do
     236                 :             :    end do
     237   [ #  #  #  # ]:           0 :    constr_rhs = zero
     238   [ #  #  #  #  :           0 :    constr_rhs(1,1:nconst) = matmul(constraints(1,:,:),d2cart_packed(1,:))
                   #  # ]
     239   [ #  #  #  #  :           0 :    constr_rhs(2,1:nconst) = matmul(constraints(1,:,:),d2cart_packed(2,:))
                   #  # ]
     240                 :             : 
     241                 :             : !  lwork = 3*nd2_packed
     242                 :             :    call zgelss (nconst,nd2_packed,1,constraints,nconst,constr_rhs,nd2_packed,&
     243                 :           0 : &   singvals,-one,constrank,work,3*nd2_packed,rwork,info)
     244         [ #  # ]:           0 :    ABI_CHECK(info == 0, sjoin('zgelss returned:', itoa(info)))
     245                 :             : 
     246                 :             : !  unpack
     247         [ #  # ]:           0 :    do ipert2=1,natom
     248         [ #  # ]:           0 :      do idir2=1,3
     249         [ #  # ]:           0 :        do ipert1=1,natom
     250         [ #  # ]:           0 :          do idir1=1,3
     251                 :           0 :            imatelem = packingindex(idir1,ipert1,idir2,ipert2)
     252         [ #  # ]:           0 :            if (imatelem == -1) then
     253                 :           0 :              imatelem = packingindex(idir2,ipert2,idir1,ipert1)
     254                 :             : !            NOTE: should complex conjugate the correction below.
     255                 :             :            end if
     256         [ #  # ]:           0 :            d2asr(:,idir1,ipert1,idir2,ipert2) = constr_rhs(:,imatelem)
     257                 :             :          end do
     258                 :             :        end do
     259                 :             :      end do
     260                 :             :    end do
     261                 :             : 
     262         [ #  # ]:           0 :    ABI_FREE(constraints)
     263         [ #  # ]:           0 :    ABI_FREE(d2cart_packed)
     264         [ #  # ]:           0 :    ABI_FREE(singvals)
     265         [ #  # ]:           0 :    ABI_FREE(constr_rhs)
     266         [ #  # ]:           0 :    ABI_FREE(work)
     267         [ #  # ]:           0 :    ABI_FREE(rwork)
     268         [ #  # ]:           0 :    ABI_FREE(packingindex)
     269                 :             :  end if
     270                 :             : 
     271                 :             : end subroutine asria_calc
     272                 :             : !!***
     273                 :             : 
     274                 :             : !----------------------------------------------------------------------
     275                 :             : 
     276                 :             : !!****f* m_dynmat/asria_corr
     277                 :             : !! NAME
     278                 :             : !! asria_corr
     279                 :             : !!
     280                 :             : !! FUNCTION
     281                 :             : !! Imposition of the Acoustic sum rule on the InterAtomic Forces
     282                 :             : !! or on the dynamical matrix directly from the previously calculated d2asr
     283                 :             : !!
     284                 :             : !! INPUTS
     285                 :             : !! asr=(0 => no ASR, 1 or 2=> the diagonal element is modified to give the ASR,
     286                 :             : !!      5 => impose hermitian solution using lapack call)
     287                 :             : !! d2asr=matrix used to store the correction needed to fulfill
     288                 :             : !! the acoustic sum rule.
     289                 :             : !! mpert =maximum number of ipert
     290                 :             : !! natom=number of atom
     291                 :             : !!
     292                 :             : !! OUTPUT
     293                 :             : !! Input/Output:
     294                 :             : !! d2cart=matrix of second derivatives of total energy, in cartesian coordinates
     295                 :             : !!
     296                 :             : !! SOURCE
     297                 :             : 
     298                 :         255 : subroutine asria_corr(asr,d2asr,d2cart,mpert,natom)
     299                 :             : 
     300                 :             : !Arguments -------------------------------
     301                 :             : !scalars
     302                 :             :  integer,intent(in) :: asr,mpert,natom
     303                 :             : !arrays
     304                 :             :  real(dp),intent(in) :: d2asr(2,3,natom,3,natom)
     305                 :             :  real(dp),intent(inout) :: d2cart(2,3,mpert,3,mpert)
     306                 :             : 
     307                 :             : !Local variables-------------------------------
     308                 :             : !scalars
     309                 :             :  integer :: idir1,idir2,ipert1,ipert2
     310                 :             : ! *********************************************************************
     311                 :             : 
     312         [ +  - ]:         255 :  if (asr==0) return
     313                 :             :  !call wrtout(std_out,' asria_corr: imposition of the ASR for the interatomic forces.')
     314                 :             : 
     315                 :             :  ! Remove d2asr
     316         [ +  + ]:         961 :  do ipert2=1,natom
     317         [ +  + ]:        3079 :    do idir2=1,3
     318         [ +  + ]:       11518 :      do ipert1=1,natom
     319         [ +  + ]:       36894 :        do idir1=1,3
     320         [ +  + ]:       86940 :          d2cart(:,idir1,ipert1,idir2,ipert2)= d2cart(:,idir1,ipert1,idir2,ipert2) - d2asr(:,idir1,ipert1,idir2,ipert2)
     321                 :             :        end do
     322                 :             :      end do
     323                 :             :    end do
     324                 :             :  end do
     325                 :             : 
     326                 :             : end subroutine asria_corr
     327                 :             : !!***
     328                 :             : 
     329                 :             : !----------------------------------------------------------------------
     330                 :             : 
     331                 :             : !!****f* m_dynmat/asrprs
     332                 :             : !! NAME
     333                 :             : !! asrprs
     334                 :             : !!
     335                 :             : !! FUNCTION
     336                 :             : !! Imposition of the Acoustic sum rule on the InterAtomic Forces Plus Rotational Symmetry
     337                 :             : !!
     338                 :             : !! INPUTS
     339                 :             : !!  asr=(3 => 1D systems, all elements are modified to give ASR and
     340                 :             : !!            rotational symmetry)
     341                 :             : !!      (4 => 0D systems, all elements are modified to give ASR and
     342                 :             : !!            rotational symmetry)
     343                 :             : !!  asrflg=(1 => the correction to enforce asr is computed from
     344                 :             : !!           d2cart, but NOT applied;
     345                 :             : !!          2 => one uses the previously determined correction)
     346                 :             : !!  minvers=previously calculated inverted coefficient matrix
     347                 :             : !!  mpert =maximum number of ipert
     348                 :             : !!  natom=number of atom
     349                 :             : !!  rotinv=(1,2,3 => for linear systems along x,y,z
     350                 :             : !!          4 => non-linear molecule
     351                 :             : !!  xcart=cartesian coordinates of the ions
     352                 :             : !!
     353                 :             : !! OUTPUT
     354                 :             : !!  (see side effects)
     355                 :             : !!
     356                 :             : !! SIDE EFFECTS
     357                 :             : !! Input/Output:
     358                 :             : !! d2cart=matrix of second derivatives of total energy, in cartesian coordinates
     359                 :             : !! minvers=inverse of the supermatrix for future application of the corrections
     360                 :             : !!
     361                 :             : !! SOURCE
     362                 :             : 
     363                 :          24 : subroutine asrprs(asr,asrflag,rotinv,uinvers,vtinvers,singular,d2cart,mpert,natom,xcart)
     364                 :             : 
     365                 :             : !Arguments ------------------------------------
     366                 :             : !scalars
     367                 :             :  integer,intent(in) :: asr,asrflag,mpert,natom,rotinv
     368                 :             : !arrays
     369                 :             :  real(dp),intent(in) :: xcart(3,natom)
     370                 :             :  real(dp),intent(inout) :: d2cart(2,3,mpert,3,mpert)
     371                 :             :  real(dp),intent(inout) :: singular(1:3*natom*(3*natom-1)/2)
     372                 :             :  real(dp),intent(inout) :: uinvers(1:3*natom*(3*natom-1)/2,1:3*natom*(3*natom-1)/2)
     373                 :             :  real(dp),intent(inout) :: vtinvers(1:3*natom*(3*natom-1)/2,1:3*natom*(3*natom-1)/2)
     374                 :             : 
     375                 :             : !Local variables-------------------------------
     376                 :             : !scalars
     377                 :             :  integer :: column,idir1,idir2,ii,info,ipert1,ipert2,jj,n3,row,superdim
     378                 :             :  real(dp) :: rcond,test
     379                 :             : ! real(dp) :: tau ! tau is present but commented out in this routine
     380                 :             :  character(len=500) :: msg
     381                 :             : !arrays
     382                 :          48 :  integer :: check(3,natom,3)
     383                 :          48 :  real(dp) :: tmp(natom,3,3),weightf(1:natom,1:natom)
     384                 :          24 :  real(dp),allocatable :: d2cartold(:,:,:,:,:),d2vecc(:),d2veccnew(:),d2vecr(:)
     385                 :          24 :  real(dp),allocatable :: d2vecrnew(:),superm(:,:),umatrix(:,:),vtmatrix(:)
     386                 :          24 :  real(dp),allocatable :: work(:)
     387                 :             : ! *********************************************************************
     388                 :             : 
     389         [ -  + ]:          24 :  if(asr/=3 .and. asr/=4)then
     390                 :             :    write(msg,'(3a,i0)')&
     391                 :           0 :    'The argument asr should be 3 or 4,',ch10, 'however, asr = ',asr
     392                 :           0 :    ABI_BUG(msg)
     393                 :             :  end if
     394                 :             : 
     395         [ +  - ]:          24 :  if (asr==3.or.asr==4)then
     396                 :          24 :    write(msg, '(a,a)' ) ch10, &
     397                 :          48 :    'asrprs: imposition of the ASR for the interatomic forces and rotational invariance'
     398                 :          24 :    call wrtout(std_out,msg)
     399                 :             :  end if
     400                 :             : 
     401                 :          24 :  write(msg,'(a,i0)')' asrflag is ', asrflag
     402         [ +  + ]:          72 :  call wrtout([std_out, ab_out], msg)
     403                 :             : 
     404                 :             : !variables for the dimensions of the matrices
     405                 :             : 
     406                 :             : !n1=3*natom*(3*natom-1)/2
     407                 :             : !n2=9*natom
     408                 :          24 :  n3=3*natom
     409                 :             : 
     410                 :          24 :  superdim=9*natom*(natom-1)/2+n3
     411                 :             : 
     412   [ -  +  +  -  :          72 :  ABI_MALLOC(d2vecr,(1:superdim))
          +  -  +  -  -  
                +  -  + ]
     413   [ -  +  +  -  :          48 :  ABI_MALLOC(d2vecc,(1:superdim))
             -  +  -  + ]
     414         [ +  + ]:         384 :  d2vecr=0d0
     415         [ +  + ]:         384 :  d2vecc=0d0
     416                 :             : 
     417                 :             : !should be changed set to delta function for debugging
     418   [ +  +  +  + ]:         168 :  weightf=1d0
     419                 :             : !tau=1d-10
     420         [ +  + ]:          72 :  do ii=1, natom
     421                 :             : !  do jj=1, ii-1
     422                 :             : !  weightf(ii,jj)= &
     423                 :             : !  &     ((xcart(1,ii)-xcart(1,jj))**2+(xcart(2,ii)-xcart(2,jj))**2+(xcart(3,ii)-xcart(3,jj))**2)**tau
     424                 :             : !  enddo
     425                 :          72 :    weightf(ii,ii)=0d0
     426                 :             :  end do
     427                 :             : 
     428   [ -  +  +  -  :         120 :  ABI_MALLOC(d2cartold,(2,3,mpert,3,mpert))
          +  -  -  +  +  
          -  +  -  +  -  
             -  +  -  + ]
     429                 :             : 
     430   [ -  +  +  +  :      163488 :  d2cartold=d2cart
          +  +  +  +  +  
                +  +  + ]
     431                 :             : 
     432                 :             : !setup vector with uncorrected derivatives
     433                 :             : 
     434         [ +  + ]:          72 :  do ipert1=1, natom
     435         [ +  + ]:          96 :    do ipert2=1, ipert1-1
     436         [ +  + ]:         144 :      do idir1=1,3
     437         [ +  + ]:         312 :        do idir2=1,3
     438                 :         216 :          row=n3+9*(ipert1-1)*(ipert1-2)/2+9*(ipert2-1)+3*(idir1-1)+idir2
     439         [ +  + ]:         216 :          if(abs(d2cart(1,idir1,ipert1,idir2,ipert2))<1d-6)then
     440                 :         110 :            d2cart(1,idir1,ipert1,idir2,ipert2)=0d0
     441                 :             :          else
     442                 :         106 :            d2vecr(row)=4*weightf(ipert1,ipert2)*d2cart(1,idir1,ipert1,idir2,ipert2)
     443                 :             :          end if
     444         [ +  + ]:         288 :          if(abs(d2cart(2,idir1,ipert1,idir2,ipert2))<1d-6) then
     445                 :         126 :            d2cart(2,idir1,ipert1,idir2,ipert2)=0d0
     446                 :             :          else
     447                 :          90 :            d2vecc(row)=4*weightf(ipert1,ipert2)*d2cart(2,idir1,ipert1,idir2,ipert2)
     448                 :             :          end if
     449                 :             :        end do
     450                 :             :      end do
     451                 :             :    end do
     452                 :             :  end do
     453                 :             : 
     454         [ +  + ]:          24 :  if(asrflag==1) then !calculate the pseudo-inverse of the supermatrix
     455   [ -  +  +  -  :           8 :    ABI_MALLOC(superm,(1:superdim,1:superdim))
          -  +  +  -  +  
          -  +  -  -  +  
                   -  + ]
     456                 :             : 
     457   [ +  +  +  + ]:         482 :    superm=0d0
     458                 :             : 
     459                 :             : !  Setting up the supermatrix containing G, A, D
     460                 :             : 
     461         [ +  + ]:           6 :    do ipert1=1, natom
     462         [ +  + ]:          16 :      do idir1=1, 3
     463                 :             : !      Setting up G
     464                 :          12 :        idir2=mod(idir1,3)+1
     465                 :          12 :        row=3*(ipert1-1)+idir1
     466         [ +  + ]:          18 :        do ipert2=1, ipert1-1
     467                 :           6 :          column=9*(ipert1-1)*(ipert1-2)/2+9*(ipert2-1)+3*(rotinv-1)+idir1
     468                 :           6 :          superm(column,row)=xcart(idir2,ipert2)-xcart(idir2,ipert1)
     469                 :           6 :          column=9*(ipert1-1)*(ipert1-2)/2+9*(ipert2-1)+3*(rotinv-1)+idir2
     470                 :          18 :          superm(column,row)=xcart(idir1,ipert1)-xcart(idir1,ipert2)
     471                 :             :        end do
     472         [ +  + ]:          22 :        do ipert2=ipert1+1, natom
     473                 :           6 :          column=9*(ipert2-1)*(ipert2-2)/2+9*(ipert1-1)+3*(idir1-1)+rotinv
     474                 :           6 :          superm(column,row)=xcart(idir2,ipert2)-xcart(idir2,ipert1)
     475                 :           6 :          column=9*(ipert2-1)*(ipert2-2)/2+9*(ipert1-1)+3*(idir2-1)+rotinv
     476                 :          18 :          superm(column,row)=xcart(idir1,ipert1)-xcart(idir1,ipert2)
     477                 :             :        end do
     478                 :             :      end do
     479         [ +  + ]:          18 :      do idir1=1, 3
     480                 :             : !      Setting up D
     481                 :          12 :        idir2=mod(idir1,3)+1
     482                 :          12 :        ii=mod(idir1+1,3)+1
     483         [ +  + ]:          18 :        do ipert2=1, ipert1-1
     484                 :           6 :          row=n3+9*(ipert1-1)*(ipert1-2)/2+9*(ipert2-1)+3*(rotinv-1)+idir1
     485                 :           6 :          column=9*natom*(natom-1)/2+3*(ipert1-1)+idir1
     486                 :           6 :          superm(column,row)=superm(column,row)+xcart(idir2,ipert2)-xcart(idir2,ipert1)
     487                 :           6 :          column=9*natom*(natom-1)/2+3*(ipert1-1)+ii
     488                 :           6 :          superm(column,row)=superm(column,row)+xcart(ii,ipert1)-xcart(ii,ipert2)
     489                 :           6 :          row=n3+9*(ipert1-1)*(ipert1-2)/2+9*(ipert2-1)+3*(idir1-1)+rotinv
     490                 :           6 :          column=9*natom*(natom-1)/2+3*(ipert2-1)+idir1
     491                 :           6 :          superm(column,row)=superm(column,row)+xcart(idir2,ipert1)-xcart(idir2,ipert2)
     492                 :           6 :          column=9*natom*(natom-1)/2+3*(ipert2-1)+ii
     493                 :          18 :          superm(column,row)=superm(column,row)+xcart(ii,ipert2)-xcart(ii,ipert1)
     494                 :             :        end do
     495                 :             : !      Setting up A
     496         [ +  + ]:          52 :        do idir2=1, 3
     497         [ +  + ]:          66 :          do ipert2=1, ipert1-1
     498                 :          18 :            column=9*(ipert1-1)*(ipert1-2)/2+9*(ipert2-1)+3*(idir1-1)+idir2
     499                 :          18 :            row=n3+column
     500                 :          54 :            superm(column,row)=4*weightf(ipert1,ipert2)
     501                 :             :          end do
     502                 :             :        end do
     503                 :             :      end do
     504                 :             :    end do
     505                 :             : 
     506                 :             : !  calculate the pseudo-inverse of the supermatrix
     507                 :             : 
     508   [ -  +  +  -  :           6 :    ABI_MALLOC(work,(1:6*superdim))
          +  -  +  -  -  
                +  -  + ]
     509   [ -  +  +  -  :           4 :    ABI_MALLOC(vtmatrix,(1:superdim))
             -  +  -  + ]
     510   [ -  +  +  -  :           6 :    ABI_MALLOC(umatrix,(1:superdim,1:superdim))
          -  +  +  -  -  
                +  -  + ]
     511                 :             : 
     512                 :             : !  singular value decomposition of superm
     513                 :             : 
     514                 :             :    call dgesvd('A','O',superdim,superdim,superm,superdim,singular,umatrix,superdim, &
     515                 :           2 :                vtmatrix, 1, work,6*superdim,info)
     516         [ -  + ]:           2 :    ABI_CHECK(info == 0, sjoin('dgesvd returned:', itoa(info)))
     517                 :             : 
     518         [ -  + ]:           2 :    ABI_FREE(vtmatrix)
     519         [ -  + ]:           2 :    ABI_FREE(work)
     520                 :             : 
     521                 :           2 :    write(msg, '(a,es16.8,es16.8)' )' Largest and smallest values from svd', singular(1), singular(superdim)
     522         [ +  + ]:           6 :    call wrtout([std_out, ab_out], msg)
     523                 :             : 
     524                 :             : !  Invert U and V**T, orthogonal matrices
     525                 :             : 
     526   [ +  +  +  + ]:         482 :    uinvers = transpose(umatrix)
     527   [ +  +  +  + ]:         482 :    vtinvers = transpose(superm)
     528                 :             : 
     529         [ -  + ]:           2 :    ABI_FREE(umatrix)
     530         [ -  + ]:           2 :    ABI_FREE(superm)
     531                 :             : 
     532                 :           2 :    write(msg,'(a,a)')' asrprs: done with asrflag 1', ch10
     533                 :           2 :    call wrtout(std_out,msg)
     534                 :             : 
     535                 :             :  end if !asrflag=1
     536                 :             : 
     537         [ +  + ]:          24 :  if(asrflag==2) then
     538                 :             : 
     539   [ -  +  +  -  :          66 :    ABI_MALLOC(d2vecrnew,(1:superdim))
          +  -  +  -  -  
                +  -  + ]
     540   [ -  +  +  -  :          44 :    ABI_MALLOC(d2veccnew,(1:superdim))
             -  +  -  + ]
     541                 :             : 
     542                 :             : !  Calculate V**T**-1 Sigma**-1 U**-1 *rhs
     543                 :             : 
     544   [ +  -  -  +  :        5632 :    d2vecrnew = matmul(uinvers, d2vecr)
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  +  +  +  +  
                   +  + ]
     545   [ +  -  -  +  :        5632 :    d2veccnew = matmul(uinvers, d2vecc)
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  +  +  +  +  
                   +  + ]
     546                 :             : 
     547                 :          22 :    rcond=1d-10*singular(1)
     548         [ +  + ]:         352 :    do ii=1, superdim
     549         [ +  + ]:         352 :      if(singular(ii)>rcond) then
     550                 :         286 :        d2vecrnew(ii)=d2vecrnew(ii)/singular(ii)
     551                 :         286 :        d2veccnew(ii)=d2veccnew(ii)/singular(ii)
     552                 :             :      else
     553                 :          44 :        d2vecrnew(ii)=0d0
     554                 :          44 :        d2veccnew(ii)=0d0
     555                 :             :      end if
     556                 :             :    end do
     557                 :             : 
     558         [ +  + ]:         352 :    do ii=1, superdim
     559                 :         330 :      d2vecr(ii)=0d0
     560                 :         330 :      d2vecc(ii)=0d0
     561         [ +  + ]:        5302 :      do jj=1, superdim
     562                 :        4950 :        d2vecr(ii)=d2vecr(ii)+vtinvers(ii,jj)*d2vecrnew(jj)
     563                 :        5280 :        d2vecc(ii)=d2vecc(ii)+vtinvers(ii,jj)*d2veccnew(jj)
     564                 :             :      end do
     565                 :             :    end do
     566                 :             : 
     567                 :             : !  Store vector back into the matrix of 2nd order derivates
     568                 :             : 
     569         [ +  + ]:          66 :    do ipert1=1, natom
     570         [ +  + ]:          88 :      do ipert2=1, ipert1-1
     571         [ +  + ]:         132 :        do idir1=1,3
     572         [ +  + ]:         286 :          do idir2=1,3
     573                 :         198 :            row=9*(ipert1-1)*(ipert1-2)/2+9*(ipert2-1)+3*(idir1-1)+idir2
     574                 :         198 :            d2cart(1,idir1,ipert1,idir2,ipert2)=d2vecr(row)
     575                 :         198 :            d2cart(2,idir1,ipert1,idir2,ipert2)=d2vecc(row)
     576                 :         198 :            d2cart(1,idir2,ipert2,idir1,ipert1)=d2vecr(row)
     577                 :         264 :            d2cart(2,idir2,ipert2,idir1,ipert1)=d2vecc(row)
     578                 :             :          end do
     579                 :             :        end do
     580                 :             :      end do
     581                 :             :    end do
     582                 :             : 
     583         [ -  + ]:          22 :    ABI_FREE(d2vecrnew)
     584         [ -  + ]:          22 :    ABI_FREE(d2veccnew)
     585                 :             : 
     586   [ +  +  +  +  :         616 :    check=0
                   +  + ]
     587                 :             : 
     588         [ +  + ]:          66 :    do ipert1=1, natom
     589         [ +  + ]:         198 :      do idir1=1, 3
     590         [ +  + ]:         572 :        do idir2=1, 3
     591                 :         396 :          d2cart(1,idir1,ipert1,idir2,ipert1)=0d0
     592                 :         396 :          d2cart(2,idir1,ipert1,idir2,ipert1)=0d0
     593                 :         396 :          tmp(ipert1,idir1,idir2)=0d0
     594         [ +  + ]:        1320 :          do ipert2=1, natom
     595         [ +  + ]:        1188 :            if(ipert2/=ipert1) then
     596                 :             :              tmp(ipert1,idir1,idir2)=tmp(ipert1,idir1,idir2) &
     597                 :             : &             -d2cart(1,idir1,ipert1,idir2,ipert2) &
     598                 :         396 : &             -d2cart(1,idir2,ipert2,idir1,ipert1)
     599                 :             :            end if
     600                 :             :          end do
     601                 :             :        end do
     602                 :             :      end do
     603                 :             :    end do
     604                 :             : 
     605         [ +  + ]:          66 :    do ipert1=1, natom
     606         [ +  + ]:         198 :      do idir1=1, 3
     607         [ +  + ]:         572 :        do idir2=1, 3
     608                 :         396 :          d2cart(1,idir1,ipert1,idir2,ipert1)=tmp(ipert1,idir1,idir2)/2
     609                 :         528 :          d2cart(1,idir2,ipert1,idir1,ipert1)=d2cart(1,idir1,ipert1,idir2,ipert1)
     610                 :             :        end do
     611                 :             :      end do
     612                 :             :    end do
     613                 :             : 
     614                 :          22 :    write(std_out,*) 'this should all be zero'
     615                 :             : 
     616         [ +  + ]:          66 :    do ipert1=1, natom
     617         [ +  + ]:         198 :      do idir1=1, 3
     618         [ +  + ]:         572 :        do idir2=1, 3
     619                 :         396 :          test=0d0
     620         [ +  + ]:        1188 :          do ipert2=1, natom
     621                 :        1188 :            test=test+d2cart(1,idir1,ipert1,idir2,ipert2)+d2cart(1,idir2,ipert2,idir1,ipert1)
     622                 :             :          end do
     623                 :         396 :          write(std_out,'(i3,i3,i3,es11.3)') idir1,ipert1,idir2,test
     624                 :             : 
     625                 :         396 :          write(msg, '(i3,i3,i3,es11.3)' ) idir1,ipert1,idir2,test
     626                 :         528 :          call wrtout(ab_out,msg)
     627                 :             :        end do
     628                 :             :      end do
     629                 :             :    end do
     630                 :             : 
     631                 :          22 :    write(std_out,*) 'these as well'
     632         [ +  + ]:          66 :    do ipert2=1, natom
     633         [ +  + ]:         198 :      do idir1=1, 3
     634         [ +  + ]:         572 :        do idir2=1, 3
     635                 :         396 :          test=0d0
     636         [ +  + ]:        1188 :          do ipert1=1, natom
     637                 :        1188 :            test=test+d2cart(1,idir1,ipert1,idir2,ipert2)
     638                 :             :          end do
     639                 :         528 :          write(std_out,'(i3,i3,i3,i3,es11.3)') idir1,ipert1,idir2,ipert2,test
     640                 :             :        end do
     641                 :             :      end do
     642                 :             :    end do
     643                 :             : 
     644                 :          22 :    write(msg,'(a,a)')' asrprs: done with asrflag 2', ch10
     645                 :          22 :    call wrtout(std_out,msg)
     646                 :             : 
     647                 :             :  end if !ends asrflag=2
     648                 :             : 
     649         [ -  + ]:          24 :  ABI_FREE(d2vecr)
     650         [ -  + ]:          24 :  ABI_FREE(d2vecc)
     651         [ -  + ]:          24 :  ABI_FREE(d2cartold)
     652                 :             : 
     653                 :          24 : end subroutine asrprs
     654                 :             : !!***
     655                 :             : 
     656                 :             : !----------------------------------------------------------------------
     657                 :             : 
     658                 :             : !!****f* m_dynmat/cart29
     659                 :             : !! NAME
     660                 :             : !! cart29
     661                 :             : !!
     662                 :             : !!
     663                 :             : !! FUNCTION
     664                 :             : !! Transform a second-derivative matrix from reduced
     665                 :             : !! coordinates to cartesian coordinates, and also
     666                 :             : !! 1) add the ionic part of the effective charges,
     667                 :             : !! 2) normalize the electronic dielectric tensor, and
     668                 :             : !!    add the vacuum polarisation
     669                 :             : !!
     670                 :             : !! INPUTS
     671                 :             : !!  blkflg(3,mpert,3,mpert,nblok)=
     672                 :             : !!   ( 1 if the element of the dynamical matrix has been calculated ;
     673                 :             : !!     0 otherwise )
     674                 :             : !!  blkval(2,3,mpert,3,mpert,nblok)=DDB values
     675                 :             : !!  gprimd(3,3)=basis vector in the reciprocal space
     676                 :             : !!  iblok=number of the blok that will be transformed
     677                 :             : !!  mpert =maximum number of ipert
     678                 :             : !!  natom=number of atom
     679                 :             : !!  nblok=number of blocks (dimension of blkflg and blkval)
     680                 :             : !!  ntypat=number of atom types
     681                 :             : !!  rprimd(3,3)=basis vector in the real space
     682                 :             : !!  typat(natom)=integer label of each type of atom (1,2,...)
     683                 :             : !!  ucvol=unit cell volume
     684                 :             : !!  zion(ntypat)=charge corresponding to the atom type
     685                 :             : !!
     686                 :             : !! OUTPUT
     687                 :             : !!  carflg(3,mpert,3,mpert)= ( 1 if the element of the cartesian
     688                 :             : !!  2DTE matrix has been calculated correctly ; 0 otherwise )
     689                 :             : !!  d2cart(2,3,mpert,3,mpert)=
     690                 :             : !!    dynamical matrix, effective charges, dielectric tensor,....
     691                 :             : !!    all in cartesian coordinates
     692                 :             : !!
     693                 :             : !! SOURCE
     694                 :             : 
     695                 :        2316 : subroutine cart29(blkflg,blkval,carflg,d2cart,&
     696                 :        2316 : & gprimd,iblok,mpert,natom,nblok,ntypat,rprimd,typat,ucvol,zion)
     697                 :             : 
     698                 :             : !Arguments -------------------------------
     699                 :             : !scalars
     700                 :             :  integer,intent(in) :: iblok,mpert,natom,nblok,ntypat
     701                 :             :  real(dp),intent(in) :: ucvol
     702                 :             : !arrays
     703                 :             :  integer,intent(in) :: blkflg(3,mpert,3,mpert,nblok),typat(natom)
     704                 :             :  integer,intent(out) :: carflg(3,mpert,3,mpert)
     705                 :             :  real(dp),intent(in) :: blkval(2,3,mpert,3,mpert,nblok),gprimd(3,3),rprimd(3,3)
     706                 :             :  real(dp),intent(in) :: zion(ntypat)
     707                 :             :  real(dp),intent(out) :: d2cart(2,3,mpert,3,mpert)
     708                 :             : 
     709                 :             : !Local variables -------------------------
     710                 :             : !scalars
     711                 :             :  integer :: idir1,idir2,ii,ipert1,ipert2
     712                 :             : !arrays
     713                 :             :  integer :: flg1(3),flg2(3)
     714                 :        4632 :  integer :: mflg(3,mpert,3,mpert)
     715                 :             :  real(dp) :: vec1(3),vec2(3)
     716                 :             : ! *********************************************************************
     717                 :             : 
     718                 :             : !First, copy the data blok in place.
     719   [ +  +  +  +  :    21433508 :  d2cart(:,:,:,:,:)=blkval(:,:,:,:,:,iblok)
          +  +  +  +  +  
                      + ]
     720                 :             : 
     721                 :             : !Cartesian coordinates transformation (in two steps)
     722                 :             : !First step
     723         [ +  + ]:       40874 :  do ipert1=1,mpert
     724         [ +  + ]:      750106 :    do ipert2=1,mpert
     725         [ +  + ]:     2166254 :      do ii=1,2
     726         [ +  + ]:     6383088 :        do idir1=1,3
     727         [ +  + ]:    17021568 :          do idir2=1,3
     728                 :    12766176 :            vec1(idir2)=d2cart(ii,idir1,ipert1,idir2,ipert2)
     729                 :             : !          Note here blkflg
     730                 :    17021568 :            flg1(idir2)=blkflg(idir1,ipert1,idir2,ipert2,iblok)
     731                 :             :          end do
     732                 :     4255392 :          call cart39(flg1,flg2,gprimd,ipert2,natom,rprimd,vec1,vec2)
     733         [ +  + ]:    18440032 :          do idir2=1,3
     734                 :    12766176 :            d2cart(ii,idir1,ipert1,idir2,ipert2)=vec2(idir2)
     735                 :             : !          And here carflg
     736                 :    17021568 :            carflg(idir1,ipert1,idir2,ipert2)=flg2(idir2)
     737                 :             :          end do
     738                 :             :        end do
     739                 :             :      end do
     740                 :             :    end do
     741                 :             :  end do
     742                 :             : 
     743                 :             : !Second step
     744         [ +  + ]:       40874 :  do ipert1=1,mpert
     745         [ +  + ]:      750106 :    do ipert2=1,mpert
     746         [ +  + ]:     2166254 :      do ii=1,2
     747         [ +  + ]:     6383088 :        do idir2=1,3
     748         [ +  + ]:    17021568 :          do idir1=1,3
     749                 :    12766176 :            vec1(idir1)=d2cart(ii,idir1,ipert1,idir2,ipert2)
     750                 :             : !          Note here carflg
     751                 :    17021568 :            flg1(idir1)=carflg(idir1,ipert1,idir2,ipert2)
     752                 :             :          end do
     753                 :     4255392 :          call cart39(flg1,flg2,gprimd,ipert1,natom,rprimd,vec1,vec2)
     754         [ +  + ]:    18440032 :          do idir1=1,3
     755                 :    12766176 :            d2cart(ii,idir1,ipert1,idir2,ipert2)=vec2(idir1)
     756                 :             : !          And here carflg again
     757                 :    17021568 :            carflg(idir1,ipert1,idir2,ipert2)=flg2(idir1)
     758                 :             :          end do
     759                 :             :        end do
     760                 :             :      end do
     761                 :             :    end do
     762                 :             :  end do
     763                 :             : 
     764                 :             : !For the dielectric tensor, takes into account the volume
     765                 :             : !of the unit cell, and add the unit matrix (polarization of the vacuum)
     766         [ +  + ]:        9264 :  do idir1=1,3
     767         [ +  + ]:       30108 :    do idir2=1,3
     768         [ +  + ]:       69480 :      do ii=1,2
     769                 :             :        d2cart(ii,idir1,natom+2,idir2,natom+2)=&
     770                 :       62532 : &       -four_pi/ucvol*d2cart(ii,idir1,natom+2,idir2,natom+2)
     771                 :             :      end do
     772                 :             :    end do
     773                 :             :  end do
     774                 :             : 
     775         [ +  + ]:        9264 :  do idir1=1,3
     776                 :             :    d2cart(1,idir1,natom+2,idir1,natom+2)=&
     777                 :        9264 : &   1.0_dp+d2cart(1,idir1,natom+2,idir1,natom+2)
     778                 :             :  end do
     779                 :             : 
     780                 :             : !Add the ionic charges to delta z to get the effective charges
     781         [ +  + ]:       10177 :  do ipert1=1,natom
     782         [ +  + ]:       33760 :    do idir1=1,3
     783                 :             :      d2cart(1,idir1,ipert1,idir1,natom+2)=&
     784                 :       31444 : &     zion(typat(ipert1))+d2cart(1,idir1,ipert1,idir1,natom+2)
     785                 :             :    end do
     786                 :             :  end do
     787         [ +  + ]:       10177 :  do ipert2=1,natom
     788         [ +  + ]:       33760 :    do idir2=1,3
     789                 :             :      d2cart(1,idir2,natom+2,idir2,ipert2)=&
     790                 :       31444 : &     zion(typat(ipert2))+d2cart(1,idir2,natom+2,idir2,ipert2)
     791                 :             :    end do
     792                 :             :  end do
     793                 :             : 
     794                 :             : !For the piezoelectric tensor, takes into account the volume of the unit cell
     795         [ +  + ]:        6948 :  do ipert2=natom+3,natom+4
     796         [ +  + ]:       20844 :    do idir1=1,3
     797         [ +  + ]:       60216 :      do idir2=1,3
     798         [ +  + ]:      138960 :        do ii=1,2
     799                 :             :          d2cart(ii,idir1,natom+2,idir2,ipert2)=&
     800                 :       83376 : &         (1.0_dp/ucvol)*d2cart(ii,idir1,natom+2,idir2,ipert2)
     801                 :             :          d2cart(ii,idir2,ipert2,idir1,natom+2)=&
     802                 :      125064 : &         (1.0_dp/ucvol)*d2cart(ii,idir2,ipert2,idir1,natom+2)
     803                 :             :        end do
     804                 :             :      end do
     805                 :             :    end do
     806                 :             :  end do
     807                 :             : 
     808                 :             : !MRoyo: For magnetic Zeeman perturbations, apply a negative sign to get induced magnetic moments.
     809                 :             : !Macroscopic Zeeman
     810   [ +  +  +  +  :     8667332 :  mflg= 0
             +  +  +  + ]
     811                 :        2316 :  ipert1=natom+5
     812         [ +  + ]:        9264 :  do idir1=1,3
     813         [ +  + ]:       74535 :    do ipert2= 1, natom+6 !exclude local Zeemans, to be done below
     814         [ +  + ]:      268032 :      do idir2=1,3
     815         [ +  + ]:      195813 :        if (mflg(idir1,ipert1,idir2,ipert2)==0) then
     816         [ +  + ]:      566595 :          do ii=1,2
     817                 :             :            d2cart(ii,idir1,ipert1,idir2,ipert2)=&
     818                 :      377730 : &          -one*d2cart(ii,idir1,ipert1,idir2,ipert2)
     819                 :      566595 :            mflg(idir1,ipert1,idir2,ipert2)=1
     820                 :             :          end do
     821                 :             :        end if
     822         [ +  + ]:      261084 :        if (mflg(idir2,ipert2,idir1,ipert1)==0) then
     823         [ +  + ]:      545751 :          do ii=1,2
     824                 :             :            d2cart(ii,idir2,ipert2,idir1,ipert1)=&
     825                 :      363834 : &          -one*d2cart(ii,idir2,ipert2,idir1,ipert1)
     826                 :      545751 :            mflg(idir2,ipert2,idir1,ipert1)=1
     827                 :             :          end do
     828                 :             :        end if
     829                 :             :      end do
     830                 :             :    end do
     831                 :             :  end do
     832                 :             : 
     833                 :             : !Local Zeemans
     834         [ +  + ]:        2316 :  if (mpert>natom+MPERT_MAX) then
     835         [ +  + ]:        8854 :    do ipert1= natom+12,2*natom+11
     836         [ +  + ]:       29785 :      do idir1=1,3
     837         [ +  + ]:      466319 :        do ipert2= 1, mpert
     838         [ +  + ]:     1774575 :          do idir2=1,3
     839         [ +  + ]:     1315233 :            if (mflg(idir1,ipert1,idir2,ipert2)==0) then
     840         [ +  + ]:     3508713 :              do ii=1,2
     841                 :             :                d2cart(ii,idir1,ipert1,idir2,ipert2)=&
     842                 :     2339142 : &              -one*d2cart(ii,idir1,ipert1,idir2,ipert2)
     843                 :     3508713 :                mflg(idir1,ipert1,idir2,ipert2)=1
     844                 :             :              end do
     845                 :             :            end if
     846         [ +  + ]:     1753644 :            if (mflg(idir2,ipert2,idir1,ipert1)==0) then
     847         [ +  + ]:     3445920 :              do ii=1,2
     848                 :             :                d2cart(ii,idir2,ipert2,idir1,ipert1)=&
     849                 :     2297280 : &              -one*d2cart(ii,idir2,ipert2,idir1,ipert1)
     850                 :     3445920 :                mflg(idir2,ipert2,idir1,ipert1)=1
     851                 :             :              end do
     852                 :             :            end if
     853                 :             :          end do
     854                 :             :        end do
     855                 :             :      end do
     856                 :             :    end do
     857                 :             :  end if
     858                 :             : 
     859                 :             :  !For magnetoelectric and magnetic susceptibility apply a 1/ucvol factor
     860                 :        2316 :  ipert1= natom + 2
     861                 :        2316 :  ipert2= natom + 5
     862         [ +  + ]:        9264 :  do idir1= 1, 3
     863         [ +  + ]:       30108 :    do idir2= 1, 3
     864         [ +  + ]:       69480 :      do ii=1,2
     865                 :             :        d2cart(ii,idir1,ipert1,idir2,ipert2)=&
     866                 :       41688 : &      d2cart(ii,idir1,ipert1,idir2,ipert2)/ucvol
     867                 :             :        d2cart(ii,idir2,ipert2,idir1,ipert1)=&
     868                 :       41688 : &      d2cart(ii,idir2,ipert2,idir1,ipert1)/ucvol
     869                 :             :        d2cart(ii,idir1,ipert2,idir2,ipert2)=&
     870                 :       62532 : &      d2cart(ii,idir1,ipert2,idir2,ipert2)/ucvol
     871                 :             :      end do
     872                 :             :    end do
     873                 :             :  end do
     874                 :             : 
     875                 :        2316 : end subroutine cart29
     876                 :             : !!***
     877                 :             : 
     878                 :             : !----------------------------------------------------------------------
     879                 :             : 
     880                 :             : !!****f* m_dynmat/cart39
     881                 :             : !! NAME
     882                 :             : !! cart39
     883                 :             : !!
     884                 :             : !!
     885                 :             : !! FUNCTION
     886                 :             : !! Transform a vector from reduced coordinates to cartesian coordinates,
     887                 :             : !! taking into account the perturbation from which it was derived,
     888                 :             : !! and also check the existence of the new values.
     889                 :             : !!
     890                 :             : !! INPUTS
     891                 :             : !!  flg1(3)=tell if information of each component of vec1 is valid
     892                 :             : !!  gprimd(3,3)=basis vector in the reciprocal space
     893                 :             : !!  ipert=number of the perturbation
     894                 :             : !!  natom=number of atom
     895                 :             : !!  rprimd(3,3)=basis vector in the real space
     896                 :             : !!  vec1(3)=input vector, in reduced coordinates
     897                 :             : !!
     898                 :             : !! OUTPUT
     899                 :             : !!  flg2(3)=tell if information of each component of vec2 is valid
     900                 :             : !!  vec2(3)=output vector, in cartesian coordinates
     901                 :             : !!
     902                 :             : !! SOURCE
     903                 :             : 
     904                 :    19208244 : subroutine cart39(flg1,flg2,gprimd,ipert,natom,rprimd,vec1,vec2)
     905                 :             : 
     906                 :             : !Arguments -------------------------------
     907                 :             : !scalars
     908                 :             :  integer,intent(in) :: ipert,natom
     909                 :             : !arrays
     910                 :             :  integer,intent(in) :: flg1(3)
     911                 :             :  integer,intent(out) :: flg2(3)
     912                 :             :  real(dp),intent(in) :: gprimd(3,3),rprimd(3,3),vec1(3)
     913                 :             :  real(dp),intent(out) :: vec2(3)
     914                 :             : 
     915                 :             : !Local variables -------------------------
     916                 :             : !scalars
     917                 :             :  integer :: idir,ii
     918                 :             : ! *********************************************************************
     919                 :             : 
     920                 :             : !Treat phonon-type perturbation
     921   [ +  -  +  + ]:    19208244 :  if(ipert>=1.and.ipert<=natom)then
     922                 :             : 
     923         [ +  + ]:    20703480 :    do idir=1,3
     924                 :    15527610 :      vec2(idir)=zero
     925                 :    15527610 :      flg2(idir)=1
     926         [ +  + ]:    62110440 :      do ii=1,3
     927         [ +  + ]:    62110440 :        if(abs(gprimd(idir,ii))>1.0d-10)then
     928         [ +  + ]:    22597644 :          if(flg1(ii)==1)then
     929                 :     8191981 :            vec2(idir)=vec2(idir)+gprimd(idir,ii)*vec1(ii)
     930                 :             :          else
     931                 :    14405663 :            flg2(idir)=0
     932                 :             :          end if
     933                 :             :        end if
     934                 :             :      end do
     935         [ +  + ]:    20703480 :      if(flg2(idir)==0)vec2(idir)=zero
     936                 :             :    end do
     937                 :             : 
     938                 :             : !  Treat electric field and qvec perturbations
     939   [ +  +  +  + ]:    14032374 :  else if(ipert==natom+2.or.ipert==natom+8) then
     940                 :             : !  OCL SCALAR
     941         [ +  + ]:     7975728 :    do idir=1,3
     942                 :     5981796 :      vec2(idir)=zero
     943                 :     5981796 :      flg2(idir)=1
     944                 :             : !    OCL SCALAR
     945         [ +  + ]:    23927184 :      do ii=1,3
     946         [ +  + ]:    23927184 :        if(abs(rprimd(idir,ii))>1.0d-10)then
     947         [ +  + ]:     8776740 :          if(flg1(ii)==1)then
     948                 :     1572465 :            vec2(idir)=vec2(idir)+rprimd(idir,ii)*vec1(ii)/two_pi
     949                 :             :          else
     950                 :     7204275 :            flg2(idir)=0
     951                 :             :          end if
     952                 :             :        end if
     953                 :             :      end do
     954         [ +  + ]:     7975728 :      if(flg2(idir)==0)vec2(idir)=zero
     955                 :             :    end do
     956                 :             : 
     957                 :             : !  Treat other perturbations
     958                 :             :  else
     959         [ +  + ]:    48153768 :    do idir=1,3
     960                 :    36115326 :      vec2(idir)=vec1(idir)
     961                 :    48153768 :      flg2(idir)=flg1(idir)
     962                 :             :    end do
     963                 :             :  end if
     964                 :             : 
     965                 :    19208244 : end subroutine cart39
     966                 :             : !!***
     967                 :             : 
     968                 :             : !----------------------------------------------------------------------
     969                 :             : 
     970                 :             : !!****f* m_dynmat/d2cart_to_red
     971                 :             : !! NAME
     972                 :             : !! d2cart_to_red
     973                 :             : !!
     974                 :             : !!
     975                 :             : !! FUNCTION
     976                 :             : !! Transform a second-derivative matrix from cartesian
     977                 :             : !! coordinates to reduced coordinate. Also,
     978                 :             : !! 1) remove the ionic part of the effective charges,
     979                 :             : !! 2) remove the vacuum polarisation from the dielectric tensor
     980                 :             : !!    and scale it with the unit cell volume
     981                 :             : !! In short, does the inverse operation of cart29.
     982                 :             : !!
     983                 :             : !! INPUTS
     984                 :             : !!  d2cart(2,3,mpert,3,mpert)=
     985                 :             : !!    second-derivative matrix in cartesian coordinates
     986                 :             : !!  gprimd(3,3)=basis vector in the reciprocal space
     987                 :             : !!  rprimd(3,3)=basis vector in the real space
     988                 :             : !!  mpert =maximum number of ipert
     989                 :             : !!  natom=number of atom
     990                 :             : !!
     991                 :             : !! OUTPUT
     992                 :             : !!  d2red(2,3,mpert,3,mpert)=
     993                 :             : !!    second-derivative matrix in reduced coordinates
     994                 :             : !!
     995                 :             : !! SOURCE
     996                 :             : 
     997                 :        2399 : subroutine d2cart_to_red(d2cart, d2red, gprimd, rprimd, mpert, natom, &
     998                 :        2399 : &                        ntypat,typat,ucvol,zion)
     999                 :             : 
    1000                 :             : !Arguments -------------------------------
    1001                 :             : !scalars
    1002                 :             :  integer,intent(in) :: mpert,natom,ntypat
    1003                 :             :  real(dp),intent(in) :: ucvol
    1004                 :             : !arrays
    1005                 :             :  integer,intent(in) :: typat(natom)
    1006                 :             :  real(dp),intent(in) :: d2cart(2,3,mpert,3,mpert)
    1007                 :             :  real(dp),intent(out) :: d2red(2,3,mpert,3,mpert)
    1008                 :             :  real(dp),intent(in) :: gprimd(3,3),rprimd(3,3)
    1009                 :             :  real(dp),intent(in) :: zion(ntypat)
    1010                 :             : 
    1011                 :             : !Local variables -------------------------
    1012                 :             : !scalars
    1013                 :             :  integer :: idir1,idir2,ii,ipert1,ipert2
    1014                 :             :  real(dp) :: fac
    1015                 :             : !arrays
    1016                 :             :  integer :: flg1(3),flg2(3)
    1017                 :             :  real(dp) :: vec1(3),vec2(3)
    1018                 :             :  real(dp) :: gprimdt(3,3),rprimdt(3,3)
    1019                 :             : ! *********************************************************************
    1020                 :             : 
    1021         [ +  + ]:        9596 :  flg1 = one
    1022         [ +  + ]:        9596 :  flg2 = one
    1023                 :             : 
    1024   [ +  +  +  +  :     7442479 :  d2red = d2cart
          +  +  +  +  +  
                      + ]
    1025                 :             : 
    1026                 :             : !Remove the ionic charges to z to get the change in effective charges
    1027         [ +  + ]:       10379 :  do ipert1=1,natom
    1028         [ +  + ]:       34319 :    do idir1=1,3
    1029                 :             :      d2red(1,idir1,ipert1,idir1,natom+2)=&
    1030                 :       31920 : &     d2red(1,idir1,ipert1,idir1,natom+2) - zion(typat(ipert1))
    1031                 :             :    end do
    1032                 :             :  end do
    1033         [ +  + ]:       10379 :  do ipert2=1,natom
    1034         [ +  + ]:       34319 :    do idir2=1,3
    1035                 :             :      d2red(1,idir2,natom+2,idir2,ipert2)=&
    1036                 :       31920 : &     d2red(1,idir2,natom+2,idir2,ipert2) - zion(typat(ipert2))
    1037                 :             :    end do
    1038                 :             :  end do
    1039                 :             : 
    1040                 :             :  ! Remove the vacuum polarizability from the dielectric tensor
    1041         [ +  + ]:        9596 :  do idir1=1,3
    1042                 :             :    d2red(1,idir1,natom+2,idir1,natom+2)=&
    1043                 :        9596 : &   d2red(1,idir1,natom+2,idir1,natom+2) - 1.0_dp
    1044                 :             :  end do
    1045                 :             : 
    1046                 :             : ! Scale the dielectric tensor with the volue of the unit cell
    1047         [ +  + ]:        9596 :  do idir1=1,3
    1048         [ +  + ]:       31187 :    do idir2=1,3
    1049         [ +  + ]:       71970 :      do ii=1,2
    1050                 :             :        d2red(ii,idir1,natom+2,idir2,natom+2)=&
    1051                 :       64773 : &       - (ucvol / four_pi) * d2red(ii,idir1,natom+2,idir2,natom+2)
    1052                 :             :      end do
    1053                 :             :    end do
    1054                 :             :  end do
    1055                 :             : 
    1056                 :             : !For the piezoelectric tensor, takes into account the volume of the unit cell
    1057         [ +  + ]:        7197 :  do ipert2=natom+3,natom+4
    1058         [ +  + ]:       21591 :    do idir1=1,3
    1059         [ +  + ]:       62374 :      do idir2=1,3
    1060         [ +  + ]:      143940 :        do ii=1,2
    1061                 :             :          d2red(ii,idir1,natom+2,idir2,ipert2)=&
    1062                 :       86364 : &         (ucvol)*d2red(ii,idir1,natom+2,idir2,ipert2)
    1063                 :             :          d2red(ii,idir2,ipert2,idir1,natom+2)=&
    1064                 :      129546 : &         (ucvol)*d2red(ii,idir2,ipert2,idir1,natom+2)
    1065                 :             :        end do
    1066                 :             :      end do
    1067                 :             :    end do
    1068                 :             :  end do
    1069                 :             : 
    1070                 :             : ! Reduced coordinates transformation (in two steps)
    1071                 :             : ! Note that rprimd and gprimd are swapped, compared to what cart39 expects
    1072                 :             : ! A factor of (2pi) ** 2 is added to transform the electric field perturbations
    1073                 :             : 
    1074   [ +  +  +  + ]:       31187 :  rprimdt = transpose(rprimd)
    1075   [ +  +  +  + ]:       31187 :  gprimdt = transpose(gprimd)
    1076                 :             : 
    1077                 :             : !First step
    1078         [ +  + ]:       24829 :  do ipert1=1,mpert
    1079         [ +  + ]:       22430 :    fac = one; if (ipert1==natom+2) fac = two_pi ** 2
    1080                 :             : 
    1081         [ +  + ]:      269841 :    do ipert2=1,mpert
    1082         [ +  + ]:      757466 :      do ii=1,2
    1083         [ +  + ]:     2205108 :        do idir1=1,3
    1084         [ +  + ]:     5880288 :          do idir2=1,3
    1085                 :     5880288 :            vec1(idir2)=d2red(ii,idir1,ipert1,idir2,ipert2)
    1086                 :             :          end do
    1087                 :             :          ! Transform vector from cartesian to reduced coordinates
    1088                 :     1470072 :          call cart39(flg1,flg2,rprimdt,ipert1,natom,gprimdt,vec1,vec2)
    1089         [ +  + ]:     6370312 :          do idir2=1,3
    1090                 :     5880288 :            d2red(ii,idir1,ipert1,idir2,ipert2)=vec2(idir2) * fac
    1091                 :             :          end do
    1092                 :             :        end do
    1093                 :             :      end do
    1094                 :             :    end do
    1095                 :             :  end do
    1096                 :             : 
    1097                 :             : !Second step
    1098         [ +  + ]:       24829 :  do ipert1=1,mpert
    1099         [ +  + ]:      269841 :    do ipert2=1,mpert
    1100         [ +  + ]:      245012 :      fac = one; if (ipert2==natom+2) fac = two_pi ** 2
    1101                 :             : 
    1102         [ +  + ]:      757466 :      do ii=1,2
    1103         [ +  + ]:     2205108 :        do idir2=1,3
    1104         [ +  + ]:     5880288 :          do idir1=1,3
    1105                 :     5880288 :            vec1(idir1)=d2red(ii,idir1,ipert1,idir2,ipert2)
    1106                 :             :          end do
    1107                 :             :          ! Transform vector from cartesian to reduced coordinates
    1108                 :     1470072 :          call cart39(flg1,flg2,rprimdt,ipert2,natom,gprimdt,vec1,vec2)
    1109         [ +  + ]:     6370312 :          do idir1=1,3
    1110                 :     5880288 :            d2red(ii,idir1,ipert1,idir2,ipert2)=vec2(idir1) * fac
    1111                 :             :          end do
    1112                 :             :        end do
    1113                 :             :      end do
    1114                 :             :    end do
    1115                 :             :  end do
    1116                 :             : 
    1117                 :             : 
    1118                 :        2399 : end subroutine d2cart_to_red
    1119                 :             : !!***
    1120                 :             : 
    1121                 :             : !----------------------------------------------------------------------
    1122                 :             : 
    1123                 :             : !!****f* m_dynmat/chkph3
    1124                 :             : !! NAME
    1125                 :             : !! chkph3
    1126                 :             : !!
    1127                 :             : !! FUNCTION
    1128                 :             : !! Check the completeness of the dynamical matrix and eventually send a warning
    1129                 :             : !!
    1130                 :             : !! INPUTS
    1131                 :             : !!  carflg(3,mpert,3,mpert)= ( 1 if the element of the cartesian
    1132                 :             : !!  2DTE matrix has been calculated correctly ; 0 otherwise )
    1133                 :             : !!  idir = direction of the eventual electric field
    1134                 :             : !!  mpert =maximum number of ipert
    1135                 :             : !!  natom=number of atoms in unit cell
    1136                 :             : !!
    1137                 :             : !! OUTPUT
    1138                 :             : !!  eventually send a warning message
    1139                 :             : !!
    1140                 :             : !! SOURCE
    1141                 :             : 
    1142                 :         602 : subroutine chkph3(carflg,idir,mpert,natom)
    1143                 :             : 
    1144                 :             : !Arguments -------------------------------
    1145                 :             : !scalars
    1146                 :             :  integer,intent(in) :: idir,mpert,natom
    1147                 :             : !arrays
    1148                 :             :  integer,intent(in) :: carflg(3,mpert,3,mpert)
    1149                 :             : 
    1150                 :             : !Local variables -------------------------
    1151                 :             : !scalars
    1152                 :             :  integer :: idir1,idir2,ipert1,ipert2,send
    1153                 :             :  character(len=500) :: msg
    1154                 :             : ! *********************************************************************
    1155                 :             : 
    1156                 :         602 :  send=0
    1157                 :             : 
    1158                 :             : !Check the elements of the analytical part of the dynamical matrix
    1159         [ +  + ]:        1857 :  do ipert2=1,natom
    1160         [ +  + ]:        5622 :    do idir2=1,3
    1161         [ +  + ]:       15031 :      do ipert1=1,natom
    1162         [ +  + ]:       43809 :        do idir1=1,3
    1163         [ +  + ]:       40044 :          if(carflg(idir1,ipert1,idir2,ipert2)==0)then
    1164                 :        8501 :            send=1
    1165                 :             :          end if
    1166                 :             :        end do
    1167                 :             :      end do
    1168                 :             :    end do
    1169                 :             :  end do
    1170                 :             : 
    1171                 :             : !If some electric field is present
    1172         [ +  + ]:         602 :  if(idir/=0)then
    1173                 :             : 
    1174                 :             : !  Check the dielectric constant
    1175         [ -  + ]:         219 :    if(carflg(idir,natom+2,idir,natom+2)==0)then
    1176                 :           0 :      send=1
    1177                 :             :    end if
    1178                 :             : 
    1179                 :             : !  Check the effective charges
    1180         [ +  + ]:         707 :    do ipert1=1,natom
    1181         [ +  + ]:        2171 :      do idir1=1,3
    1182         [ +  + ]:        1952 :        if(carflg(idir1,ipert1,idir,natom+2)==0)then
    1183                 :          39 :          send=1
    1184                 :             :        end if
    1185                 :             :      end do
    1186                 :             :    end do
    1187                 :             : 
    1188                 :             :  end if
    1189                 :             : 
    1190                 :             :  ! If needed, send the message
    1191         [ +  + ]:         602 :  if(send==1)then
    1192                 :             :    write(msg, '(a,a,a,a)' )&
    1193                 :          75 : &    ' chkph3 : WARNING -',ch10,&
    1194                 :         150 : &    '  Dynamical matrix incomplete, phonon frequencies may be wrong, see the log file for more explanations.'
    1195                 :          75 :    call wrtout(ab_out,msg)
    1196                 :             :    write(msg, '(11a)' )&
    1197                 :          75 : &   ' chkph3 : WARNING -',ch10,&
    1198                 :          75 : &   '  Dynamical matrix incomplete, phonon frequencies may be wrong.',ch10,&
    1199                 :          75 : &   '  Likely due to a list of perturbations, as defined by rfatpol and rfdir, that does not include',ch10,&
    1200                 :          75 : &   '  all displacements of all atoms and (if non-metallic material) electric field type perturbation.',ch10,&
    1201                 :          75 : &   '  Then, the dynamical matrix includes zeroes when the matrix element is not computed.',ch10,&
    1202                 :         150 : &   '  This is allowed for testing purposes. But the phonon frequencies may be wrong.'
    1203                 :          75 :    call wrtout(std_out,msg)
    1204                 :             :    write(msg, '(9a)' )&
    1205                 :          75 : &  '  If there are symmetries, perhaps these matrix elements are zero by symmetry anyhow, and phonon frequencies might be right.',ch10,&
    1206                 :          75 : &  '  Please check the input variables rfatpol and rfdir, to determine whether abinit is doing what you intend it to do.',ch10,&
    1207                 :          75 : &  '  Note that ANADDB is able to detect whether the symmetries allow one to reconstruct the full dynamical matrix from',ch10,&
    1208                 :          75 : &  '  an incomplete one. In this case, passing to ANADDB the delivered _DDB file might confirm (or not) that',ch10,&
    1209                 :         150 : &  '  phonon frequencies are right.'
    1210                 :          75 :    call wrtout(std_out,msg)
    1211                 :             :  end if
    1212                 :             : 
    1213                 :         602 : end subroutine chkph3
    1214                 :             : !!***
    1215                 :             : 
    1216                 :             : !----------------------------------------------------------------------
    1217                 :             : 
    1218                 :             : !!****f* m_dynmat/chneu9
    1219                 :             : !! NAME
    1220                 :             : !! chneu9
    1221                 :             : !!
    1222                 :             : !! FUNCTION
    1223                 :             : !! Imposition of the charge neutrality sum rule on the Effective charges
    1224                 :             : !! and suppress the imaginary part of the dynamical matrix
    1225                 :             : !!
    1226                 :             : !! INPUTS
    1227                 :             : !!  chneut=(0 => no ASR, 1 => equal repartition, 2 => weighted repartition )
    1228                 :             : !!  mpert =maximum number of ipert
    1229                 :             : !!  natom=number of atom
    1230                 :             : !!  ntypat=number of types of atoms in unit cell
    1231                 :             : !!  selectz=selection of some parts of the effective charge tensor attached to one atom.
    1232                 :             : !!    (0=> no selection, 1=> trace only, 2=> symmetric part only)
    1233                 :             : !!  typat(natom)=type of the atom
    1234                 :             : !!  zion(ntypat)=atomic charge for every type of atom
    1235                 :             : !!
    1236                 :             : !! SIDE EFFECTS
    1237                 :             : !!  Input/Output
    1238                 :             : !!  d2cart=matrix of second derivatives of total energy, in cartesian
    1239                 :             : !!       coordinates
    1240                 :             : !!
    1241                 :             : !! SOURCE
    1242                 :             : 
    1243                 :         194 : subroutine chneu9(chneut,d2cart,mpert,natom,ntypat,selectz,typat,zion)
    1244                 :             : 
    1245                 :             : !Arguments -------------------------------
    1246                 :             : !scalars
    1247                 :             :  integer,intent(in) :: chneut,mpert,natom,ntypat,selectz
    1248                 :             : !arrays
    1249                 :             :  integer,intent(in) :: typat(natom)
    1250                 :             :  real(dp),intent(in) :: zion(ntypat)
    1251                 :             :  real(dp),intent(inout) :: d2cart(2,3,mpert,3,mpert)
    1252                 :             : 
    1253                 :             : !Local variables -------------------------
    1254                 :             : !scalars
    1255                 :             :  integer :: idir1,idir2,ii,ipert1,ipert2
    1256                 :             :  character(len=500) :: msg
    1257                 :             : !arrays
    1258                 :             :  real(dp) :: sumwght(2)
    1259                 :         194 :  real(dp),allocatable :: wghtat(:)
    1260                 :             : ! *********************************************************************
    1261                 :             : 
    1262   [ -  +  +  -  :         582 :  ABI_MALLOC(wghtat,(natom))
          +  -  +  -  -  
                +  -  + ]
    1263                 :             : 
    1264                 :             : !In case of acoustic sum rule imposition, compute the weights on each atom.
    1265         [ +  + ]:         194 :  if (chneut==1)then
    1266                 :             : 
    1267                 :             : !  The weight is the same for all atom
    1268         [ +  + ]:         659 :    do ipert1=1,natom
    1269                 :         659 :      wghtat(ipert1)=1./natom
    1270                 :             :    end do
    1271                 :             : 
    1272         [ +  + ]:          22 :  else if (chneut==2) then
    1273                 :             : 
    1274                 :             : !  The weight is proportional to the diagonal electronic screening charge of the atom
    1275                 :          11 :    sumwght(1)=zero
    1276         [ +  + ]:          66 :    do ipert1=1,natom
    1277                 :          55 :      wghtat(ipert1)=zero
    1278         [ +  + ]:         220 :      do idir1=1,3
    1279                 :             :        wghtat(ipert1)=wghtat(ipert1)+&
    1280                 :             : &       d2cart(1,idir1,ipert1,idir1,natom+2)+&
    1281                 :         220 : &       d2cart(1,idir1,natom+2,idir1,ipert1)-2*zion(typat(ipert1))
    1282                 :             :      end do
    1283                 :          66 :      sumwght(1)=sumwght(1)+wghtat(ipert1)
    1284                 :             :    end do
    1285                 :             : 
    1286                 :             : !  Normalize the weights to unity
    1287         [ +  + ]:          66 :    wghtat(1:natom) = wghtat(1:natom) / sumwght(1)
    1288                 :             :  end if
    1289                 :             : 
    1290                 :             : !Calculation of the violation of the charge neutrality
    1291                 :             : !and imposition of the charge neutrality condition
    1292         [ +  + ]:         194 :  if (chneut/=0)then
    1293                 :             :    write(msg, '(a,a,a,a,a,a,a)' )&
    1294                 :         183 :     ' The violation of the charge neutrality conditions',ch10,&
    1295                 :         183 :     ' by the effective charges is as follows :',ch10,&
    1296                 :         183 :     '    atom        electric field',ch10,&
    1297                 :         366 :     ' displacement     direction   '
    1298                 :         183 :    call wrtout(ab_out,msg)
    1299         [ +  + ]:         732 :    do idir1=1,3
    1300         [ +  + ]:        2379 :      do idir2=1,3
    1301         [ +  + ]:        4941 :        do ii=1,2
    1302                 :        3294 :          sumwght(ii)=zero
    1303         [ +  + ]:       13050 :          do ipert1=1,natom
    1304                 :       13050 :            sumwght(ii)=sumwght(ii)+d2cart(ii,idir1,ipert1,idir2,natom+2)
    1305                 :             :          end do
    1306         [ +  + ]:       14697 :          do ipert1=1,natom
    1307                 :             :            d2cart(ii,idir1,ipert1,idir2,natom+2)=&
    1308                 :       13050 :            d2cart(ii,idir1,ipert1,idir2,natom+2)-sumwght(ii)*wghtat(ipert1)
    1309                 :             :          end do
    1310                 :             :        end do
    1311                 :        1647 :        write(msg, '(i8,i16,2f16.6)' ) idir1,idir2,sumwght(1),sumwght(2)
    1312                 :        2196 :        call wrtout(ab_out,msg)
    1313                 :             :      end do
    1314                 :             :    end do
    1315                 :         183 :    write(msg, '(a)' )' '
    1316                 :         183 :    call wrtout(ab_out,msg)
    1317                 :             : 
    1318                 :             : !  The same for the symmetrical part
    1319         [ +  + ]:         732 :    do idir1=1,3
    1320         [ +  + ]:        2379 :      do idir2=1,3
    1321         [ +  + ]:        5490 :        do ii=1,2
    1322                 :        3294 :          sumwght(ii)=zero
    1323         [ +  + ]:       13050 :          do ipert2=1,natom
    1324                 :       13050 :            sumwght(ii)=sumwght(ii)+d2cart(ii,idir1,natom+2,idir2,ipert2)
    1325                 :             :          end do
    1326         [ +  + ]:       14697 :          do ipert2=1,natom
    1327                 :             :            d2cart(ii,idir1,natom+2,idir2,ipert2)=&
    1328                 :       13050 :            d2cart(ii,idir1,natom+2,idir2,ipert2)-sumwght(ii)*wghtat(ipert2)
    1329                 :             :          end do
    1330                 :             :        end do
    1331                 :             :      end do
    1332                 :             :    end do
    1333                 :             :  end if
    1334                 :             : 
    1335                 :             : !Selection of the trace of the effective charge tensor attached to each atom
    1336         [ -  + ]:         194 :  if(selectz==1)then
    1337         [ #  # ]:           0 :    do ipert1=1,natom
    1338         [ #  # ]:           0 :      do ii=1,2
    1339                 :           0 :        sumwght(ii)=zero
    1340         [ #  # ]:           0 :        do idir1=1,3
    1341                 :           0 :          sumwght(ii)=sumwght(ii)+d2cart(ii,idir1,ipert1,idir1,natom+2)
    1342                 :             :        end do
    1343         [ #  # ]:           0 :        do idir1=1,3
    1344         [ #  # ]:           0 :          do idir2=1,3
    1345                 :           0 :            d2cart(ii,idir1,ipert1,idir2,natom+2)=zero
    1346                 :             :          end do
    1347                 :             :        end do
    1348         [ #  # ]:           0 :        do idir1=1,3
    1349                 :           0 :          d2cart(ii,idir1,ipert1,idir1,natom+2)=sumwght(ii)/3.0_dp
    1350                 :             :        end do
    1351                 :             :      end do
    1352                 :             :    end do
    1353                 :             : !  Do the same for the symmetrical part of d2cart
    1354         [ #  # ]:           0 :    do ipert2=1,natom
    1355         [ #  # ]:           0 :      do ii=1,2
    1356                 :           0 :        sumwght(ii)=zero
    1357         [ #  # ]:           0 :        do idir1=1,3
    1358                 :           0 :          sumwght(ii)=sumwght(ii)+d2cart(ii,idir1,natom+2,idir1,ipert2)
    1359                 :             :        end do
    1360         [ #  # ]:           0 :        do idir1=1,3
    1361         [ #  # ]:           0 :          do idir2=1,3
    1362                 :           0 :            d2cart(ii,idir1,natom+2,idir2,ipert2)=zero
    1363                 :             :          end do
    1364                 :             :        end do
    1365         [ #  # ]:           0 :        do idir1=1,3
    1366                 :           0 :          d2cart(ii,idir1,natom+2,idir1,ipert2)=sumwght(ii)/3.0_dp
    1367                 :             :        end do
    1368                 :             :      end do
    1369                 :             :    end do
    1370                 :             :  end if
    1371                 :             : 
    1372                 :             : !Selection of the symmetric part of the effective charge tensor attached to each atom
    1373         [ -  + ]:         194 :  if(selectz==2)then
    1374         [ #  # ]:           0 :    do ipert1=1,natom
    1375         [ #  # ]:           0 :      do ii=1,2
    1376         [ #  # ]:           0 :        do idir1=1,3
    1377         [ #  # ]:           0 :          do idir2=1,3
    1378                 :             :            sumwght(ii)=(d2cart(ii,idir1,ipert1,idir2,natom+2)&
    1379                 :           0 : &           +d2cart(ii,idir2,ipert1,idir1,natom+2))/2.0_dp
    1380                 :           0 :            d2cart(ii,idir1,ipert1,idir2,natom+2)=sumwght(ii)
    1381                 :           0 :            d2cart(ii,idir2,ipert1,idir1,natom+2)=sumwght(ii)
    1382                 :             :          end do
    1383                 :             :        end do
    1384                 :             :      end do
    1385                 :             :    end do
    1386                 :             : !  Do the same for the symmetrical part of d2cart
    1387         [ #  # ]:           0 :    do ipert1=1,natom
    1388         [ #  # ]:           0 :      do ii=1,2
    1389         [ #  # ]:           0 :        do idir1=1,3
    1390         [ #  # ]:           0 :          do idir2=1,3
    1391                 :             :            sumwght(ii)=(d2cart(ii,idir1,ipert1,idir2,natom+2)&
    1392                 :           0 : &           +d2cart(ii,idir2,ipert1,idir1,natom+2))/2.0_dp
    1393                 :           0 :            d2cart(ii,idir1,ipert1,idir2,natom+2)=sumwght(ii)
    1394                 :           0 :            d2cart(ii,idir2,ipert1,idir1,natom+2)=sumwght(ii)
    1395                 :             :          end do
    1396                 :             :        end do
    1397                 :             :      end do
    1398                 :             :    end do
    1399                 :             :  end if
    1400                 :             : 
    1401                 :             : !Write the effective charge tensor
    1402                 :             :  write(msg, '(a,a,a,a,a,a,a)' )&
    1403                 :         194 :    ' Effective charge tensors after ',ch10,&
    1404                 :         194 :    ' imposition of the charge neutrality (if requested by user),',ch10,&
    1405                 :         194 :    ' and eventual restriction to some part :',ch10,&
    1406                 :         388 :   '   atom    displacement  '
    1407                 :         194 :  call wrtout(ab_out,msg)
    1408                 :             : 
    1409         [ +  + ]:         770 :  do ipert1=1,natom
    1410         [ +  + ]:        2498 :    do idir1=1,3
    1411   [ +  -  +  + ]:        6912 :      write(msg, '(2i10,3es16.6)' )ipert1,idir1,(d2cart(1,idir1,ipert1,idir2,natom+2),idir2=1,3)
    1412                 :        2304 :      call wrtout(ab_out,msg)
    1413                 :             :    end do
    1414                 :             :  end do
    1415                 :             : 
    1416                 :             : !Zero the imaginary part of the dynamical matrix
    1417                 :         194 :  write(msg, '(a)' )' Now, the imaginary part of the dynamical matrix is zeroed '
    1418                 :         194 :  call wrtout(ab_out,msg)
    1419                 :         194 :  call wrtout(std_out,msg)
    1420                 :             : 
    1421   [ +  +  +  +  :       32474 :  d2cart(2, 1:3, 1:natom, 1:3, 1:natom) = zero
             +  +  +  + ]
    1422                 :             : 
    1423         [ -  + ]:         194 :  ABI_FREE(wghtat)
    1424                 :             : 
    1425                 :         194 : end subroutine chneu9
    1426                 :             : !!***
    1427                 :             : 
    1428                 :             : !----------------------------------------------------------------------
    1429                 :             : 
    1430                 :             : !!****f* m_dynmat/d2sym3
    1431                 :             : !! NAME
    1432                 :             : !! d2sym3
    1433                 :             : !!
    1434                 :             : !! FUNCTION
    1435                 :             : !! Given a set of calculated elements of the 2DTE matrix d2,
    1436                 :             : !! build (nearly) all the other matrix elements that can be build using symmetries.
    1437                 :             : !!
    1438                 :             : !! 1. Perform first some completion by symmetrisation (exchange)
    1439                 :             : !!    over the two defining perturbations
    1440                 :             : !! 2. For each element, uses every symmetry, and build the element, in case
    1441                 :             : !!    EITHER all the needed elements are available,
    1442                 :             : !!    OR the only missing is itself
    1443                 :             : !!    OR the perturbation is the electric field, in a diamond
    1444                 :             : !!    symmetry (the last case was coded rather dirty)
    1445                 :             : !!
    1446                 :             : !! INPUTS
    1447                 :             : !!  indsym(4,nsym,natom)=indirect indexing array : for each
    1448                 :             : !!   isym,iatom, fourth element is label of atom into which iatom is sent by
    1449                 :             : !!   INVERSE of symmetry operation isym; first three elements are the primitive
    1450                 :             : !!   translations which must be subtracted after the transformation to get back
    1451                 :             : !!   to the original unit cell.
    1452                 :             : !!  mpert =maximum number of ipert
    1453                 :             : !!  natom= number of atoms
    1454                 :             : !!  nsym=number of space group symmetries
    1455                 :             : !!  qpt(3)=wavevector of the perturbation
    1456                 :             : !!  symq(4,2,nsym)= (integer) three first numbers define the G vector ;
    1457                 :             : !!   fourth number is zero if the q-vector is not preserved,
    1458                 :             : !!              is 1 otherwise
    1459                 :             : !!   second index is one without time-reversal symmetry,
    1460                 :             : !!                two with time-reversal symmetry
    1461                 :             : !!  symrec(3,3,nsym)=3x3 matrices of the group symmetries (reciprocal space)
    1462                 :             : !!  symrel(3,3,nsym)=3x3 matrices of the group symmetries (real space)
    1463                 :             : !!  timrev=1 if the time-reversal symmetry preserves the wavevector,
    1464                 :             : !!     modulo a reciprocal lattice vector, timrev=0 otherwise
    1465                 :             : !!  zero_by_symm= if 1, set blkflg to 1 for the elements that must be zero by symmetry, and zero them.
    1466                 :             : !!    This has the indirect effect of being able to resymmetrize the whole matrix, thus
    1467                 :             : !!    enforcing better the symmetry for the 2DTE.
    1468                 :             : !!
    1469                 :             : !! SIDE EFFECTS
    1470                 :             : !!  Input/Output
    1471                 :             : !!  d2(2,3,mpert,3,mpert)= matrix of the 2DTE
    1472                 :             : !!  blkflg(3,mpert,3,mpert)= ( 1 if the element of the dynamical
    1473                 :             : !!     matrix has been calculated ; 0 otherwise)
    1474                 :             : !!
    1475                 :             : !! NOTES
    1476                 :             : !!   The complete search would be to have the possibility
    1477                 :             : !!   of a set of missing elements. See notes of July 2, 1994,
    1478                 :             : !!   in the blue notebook 'computer codes'
    1479                 :             : !!   The partial solution adopted here takes into
    1480                 :             : !!   account some mirror symmetries
    1481                 :             : !!   as well as the tetrahedral symmetry of the diamond lattice
    1482                 :             : !!   On 010331, replaced the loops up to mpert by loops up to
    1483                 :             : !!   natom+2, because of a crash bug under Windows. However,
    1484                 :             : !!   the problem lies likely in the use of the indsym array.
    1485                 :             : !!
    1486                 :             : !! SOURCE
    1487                 :             : 
    1488                 :      174684 : subroutine d2sym3(blkflg,d2,indsym,mpert,natom,nsym,qpt,symq,symrec,symrel,timrev,zero_by_symm,eta)
    1489                 :             : 
    1490                 :             : !Arguments -------------------------------
    1491                 :             : !scalars
    1492                 :             :  integer,intent(in) :: mpert,natom,nsym,timrev,zero_by_symm
    1493                 :             : !arrays
    1494                 :             :  integer,intent(in) :: indsym(4,nsym,natom),symq(4,2,nsym)
    1495                 :             :  integer,intent(in),target :: symrec(3,3,nsym),symrel(3,3,nsym)
    1496                 :             :  integer,intent(inout) :: blkflg(3,mpert,3,mpert)
    1497                 :             :  real(dp),intent(in) :: qpt(3)
    1498                 :             :  real(dp),intent(inout) :: d2(2,3,mpert,3,mpert)
    1499                 :             :  real(dp),optional,intent(in) :: eta
    1500                 :             : 
    1501                 :             : !Local variables -------------------------
    1502                 :             : !scalars
    1503                 :             :  logical, parameter :: do_final_sym=.true.
    1504                 :             :  logical :: qzero
    1505                 :             :  integer :: exch12,found,idir1,idir2,idisy1,idisy2,ipert1,ipert2
    1506                 :             :  integer :: ipesy1,ipesy2,isgn,isym,ithree,itirev,nblkflg_is_one,noccur,nsym_used,quit,quit1
    1507                 :             :  real(dp) :: arg1,arg2,im,norm,eta_,re,sumi,sumr,xi,xr
    1508                 :             : !arrays
    1509                 :      174684 :  integer,pointer :: sym1_(:,:,:),sym2_(:,:,:)
    1510                 :      174684 :  real(dp),allocatable :: d2tmp1(:,:,:),d2tmp2(:,:,:),d2work(:,:,:,:,:)
    1511                 :             : ! *********************************************************************
    1512                 :             : 
    1513                 :      174684 :  qzero=(qpt(1)**2+qpt(2)**2+qpt(3)**2<tol16)
    1514                 :             : 
    1515                 :             : !Here look after exchange of 1 and 2 axis,
    1516                 :             : !for electric field in diamond symmetry
    1517                 :      174684 :  exch12=0
    1518                 :      174684 :  if (qzero) then
    1519         [ +  + ]:     1467366 :    do isym=1,nsym
    1520                 :     1466957 :      exch12=1
    1521         [ +  + ]:     1466957 :      if(symrel(1,1,isym)/=0)exch12=0
    1522         [ +  + ]:     1466957 :      if(symrel(1,2,isym)/=1)exch12=0
    1523         [ +  + ]:     1466957 :      if(symrel(1,3,isym)/=0)exch12=0
    1524         [ +  + ]:     1466957 :      if(symrel(2,1,isym)/=1)exch12=0
    1525         [ +  + ]:     1466957 :      if(symrel(2,2,isym)/=0)exch12=0
    1526         [ +  + ]:     1466957 :      if(symrel(2,3,isym)/=0)exch12=0
    1527         [ +  + ]:     1466957 :      if(symrel(3,1,isym)/=0)exch12=0
    1528         [ +  + ]:     1466957 :      if(symrel(3,2,isym)/=0)exch12=0
    1529         [ +  + ]:     1466957 :      if(symrel(3,3,isym)/=1)exch12=0
    1530                 :             : !    if(exch12==1) write(std_out,*)' d2sym3 : found exchange 1 2 =',isym
    1531         [ +  + ]:      390089 :      if(exch12==1)exit
    1532                 :             :    end do
    1533                 :             :  end if
    1534                 :             : 
    1535         [ +  + ]:      174684 :  eta_=zero; if(present(eta)) eta_=eta
    1536                 :             : 
    1537                 :             : !Consider two cases : either time-reversal symmetry
    1538                 :             : !conserves the wavevector, or not
    1539   [ +  +  -  + ]:      174684 :  if(timrev==0.and.abs(eta_)<tol8)then
    1540                 :             : 
    1541         [ +  + ]:      530536 :   do ipert1=1,mpert !See notes
    1542                 :             : !   do ipert1=1,min(natom+2,mpert)
    1543         [ +  + ]:     1763503 :      do idir1=1,3
    1544                 :             : 
    1545                 :             : !      Since the matrix is hermitian, the diagonal elements are real
    1546                 :     1232967 :        d2(2,idir1,ipert1,idir1,ipert1)=zero
    1547                 :             : 
    1548         [ +  + ]:     7223125 :       do ipert2=1,mpert !See notes
    1549                 :             : !       do ipert2=1,min(natom+2,mpert)
    1550         [ +  + ]:    23549643 :          do idir2=1,3
    1551                 :             : 
    1552                 :             :            ! FIXME use is_type functions
    1553                 :             : !          If an element exists
    1554         [ +  + ]:    22316676 :            if(blkflg(idir1,ipert1,idir2,ipert2)==1)then
    1555                 :             : 
    1556                 :             : !            Either complete the symmetric missing element
    1557         [ +  + ]:     2028269 :              if(blkflg(idir2,ipert2,idir1,ipert1)==0)then
    1558                 :             : 
    1559                 :        1207 :                d2(1,idir2,ipert2,idir1,ipert1)= d2(1,idir1,ipert1,idir2,ipert2)
    1560                 :        1207 :                d2(2,idir2,ipert2,idir1,ipert1)=-d2(2,idir1,ipert1,idir2,ipert2)
    1561                 :             : 
    1562                 :        1207 :                blkflg(idir2,ipert2,idir1,ipert1)=1
    1563                 :             : 
    1564                 :             : !              Or symmetrize (the matrix is hermitian) in case both exists
    1565                 :             : !              (Note : this opportunity has been disabled for more
    1566                 :             : !              obvious search for bugs in the code )
    1567                 :             : !              else
    1568                 :             : !              sumr=d2(1,idir2,ipert2,idir1,ipert1)+d2(1,idir1,ipert1,idir2,ipert2)
    1569                 :             : !              sumi=d2(1,idir2,ipert2,idir1,ipert1)-d2(1,idir1,ipert1,idir2,ipert2)
    1570                 :             : !              d2(1,idir2,ipert2,idir1,ipert1)=half*sumr
    1571                 :             : !              d2(1,idir1,ipert1,idir2,ipert2)=half*sumr
    1572                 :             : !              d2(2,idir2,ipert2,idir1,ipert1)=half*sumi
    1573                 :             : !              d2(2,idir1,ipert1,idir2,ipert2)=-half*sumi
    1574                 :             :              end if
    1575                 :             :            end if
    1576                 :             : 
    1577                 :             :          end do
    1578                 :             :        end do
    1579                 :             : 
    1580                 :             :      end do
    1581                 :             :    end do
    1582                 :             : 
    1583                 :             : !  Here, case with time-reversal symmetry
    1584                 :             :  else
    1585                 :             : 
    1586         [ +  + ]:      233408 :   do ipert1=1,mpert !See notes
    1587                 :             : !   do ipert1=1,min(natom+2,mpert)
    1588         [ +  + ]:      768221 :      do idir1=1,3
    1589         [ +  + ]:     2623655 :       do ipert2=1,mpert !See notes
    1590                 :             : !       do ipert2=1,min(natom+2,mpert)
    1591         [ +  + ]:     8177097 :          do idir2=1,3
    1592                 :     5731713 :            d2(2,idir1,ipert1,idir2,ipert2)=zero
    1593                 :             : 
    1594                 :             : !          If an element exists
    1595         [ +  + ]:     7642284 :            if(blkflg(idir1,ipert1,idir2,ipert2)==1)then
    1596                 :             : 
    1597                 :             : !            Either complete the symmetric missing element
    1598         [ +  + ]:      777755 :              if(blkflg(idir2,ipert2,idir1,ipert1)==0)then
    1599                 :             : 
    1600                 :        7392 :                d2(1,idir2,ipert2,idir1,ipert1)=d2(1,idir1,ipert1,idir2,ipert2)
    1601                 :        7392 :                blkflg(idir2,ipert2,idir1,ipert1)=1
    1602                 :             : 
    1603                 :             : !              Or symmetrize (the matrix is hermitian) in case both exists
    1604                 :             : !              (Note : this opportunity has been disabled for more
    1605                 :             : !              obvious search for bugs in the code )
    1606                 :             : !              else
    1607                 :             : !              sumr=d2(1,idir2,ipert2,idir1,ipert1)+d2(1,idir1,ipert1,idir2,ipert2)
    1608                 :             : !              d2(1,idir2,ipert2,idir1,ipert1)=half*sumr
    1609                 :             : !              d2(1,idir1,ipert1,idir2,ipert2)=half*sumr
    1610                 :             :              end if
    1611                 :             : 
    1612                 :             :            end if
    1613                 :             :          end do
    1614                 :             :        end do
    1615                 :             :      end do
    1616                 :             :    end do
    1617                 :             :  end if
    1618                 :             : 
    1619                 :             : !Big Big Loop : symmetrize three times, because
    1620                 :             : !of some cases in which one element is not yet available
    1621                 :             : !at the first pass, and even at the second one !
    1622         [ +  + ]:      698736 :  do ithree=1,3
    1623                 :             : 
    1624                 :             : !  Big loop on all elements
    1625         [ +  + ]:     2466516 :   do ipert1=1,mpert !See notes
    1626                 :             : !   do ipert1=1,min(natom+2,mpert)
    1627                 :             : 
    1628                 :             : !    Select the symmetries according to pertubation 1
    1629         [ +  + ]:     1767780 :      if (ipert1<=natom)then
    1630                 :      642921 :        sym1_ => symrec
    1631                 :             :      else
    1632                 :     1124859 :        sym1_ => symrel
    1633                 :             :      end if
    1634                 :             : 
    1635         [ +  + ]:     7595172 :      do idir1=1,3
    1636         [ +  + ]:    29540340 :       do ipert2=1,mpert !See notes
    1637                 :             : !       do ipert2=1,min(natom+2,mpert)
    1638                 :             : 
    1639                 :             :     !    Select the symmetries according to pertubation 2
    1640         [ +  + ]:    22469220 :          if (ipert2<=natom)then
    1641                 :     7576029 :            sym2_ => symrec
    1642                 :             :          else
    1643                 :    14893191 :            sym2_ => symrel
    1644                 :             :          end if
    1645                 :             : 
    1646         [ +  + ]:    95180220 :          do idir2=1,3
    1647                 :             : 
    1648                 :             : !          Will get element (idir1,ipert1,idir2,ipert2)
    1649                 :             : !          so this element should not yet be present ...
    1650         [ +  + ]:    89876880 :            if(blkflg(idir1,ipert1,idir2,ipert2)/=1)then
    1651                 :             : 
    1652                 :    57511029 :              d2(1,idir1,ipert1,idir2,ipert2)=zero
    1653                 :    57511029 :              d2(2,idir1,ipert1,idir2,ipert2)=zero
    1654                 :             : 
    1655                 :             : !            Loop on all symmetries, including time-reversal
    1656                 :    57511029 :              quit1=0
    1657         [ +  + ]:  2174579544 :              do isym=1,nsym
    1658         [ +  + ]:  6351941518 :                do itirev=1,2
    1659                 :  4234873003 :                  isgn=3-2*itirev
    1660                 :             : 
    1661         [ +  + ]:  6351941518 :                  if(symq(4,itirev,isym)/=0)then
    1662                 :  1817957213 :                    found=1
    1663                 :             : 
    1664                 :             : !                  Here select the symmetric of ipert1
    1665         [ +  + ]:  1817957213 :                    if(ipert1<=natom)then
    1666                 :   415347863 :                      ipesy1=indsym(4,isym,ipert1)
    1667   [ +  +  +  + ]:  1402609350 :                    else if(ipert1==(natom+2).and.qzero)then
    1668                 :             :                      ipesy1=ipert1
    1669                 :             :                    else
    1670                 :  1122693117 :                      found=0
    1671                 :             :                    end if
    1672                 :             : 
    1673                 :             : !                  Here select the symmetric of ipert2
    1674         [ +  + ]:  1817957213 :                    if(ipert2<=natom)then
    1675                 :   417944249 :                      ipesy2=indsym(4,isym,ipert2)
    1676   [ +  +  +  + ]:  1400012964 :                    else if(ipert2==(natom+2).and.qzero)then
    1677                 :             :                      ipesy2=ipert2
    1678                 :             :                    else
    1679                 :             :                      found=0
    1680                 :             :                    end if
    1681                 :             : 
    1682                 :             : !                  Now that a symmetric perturbation has been obtained,
    1683                 :             : !                  including the expression of the symmetry matrix, see
    1684                 :             : !                  if the symmetric values are available
    1685         [ +  + ]:   695264096 :                    if( found==1 ) then
    1686                 :             : 
    1687                 :             :                      sumr=zero
    1688                 :             :                      sumi=zero
    1689                 :             :                      noccur=0
    1690                 :             :                      nblkflg_is_one=0
    1691                 :             :                      quit=0
    1692         [ +  + ]:   505150042 :                      do idisy1=1,3
    1693         [ +  + ]:  1465573085 :                        do idisy2=1,3
    1694   [ +  +  +  + ]:  1465573085 :                          if(sym1_(idir1,idisy1,isym)/=0 .and. sym2_(idir2,idisy2,isym)/=0 )then
    1695         [ +  + ]:   273787614 :                            if(blkflg(idisy1,ipesy1,idisy2,ipesy2)==1)then
    1696                 :    40998657 :                              nblkflg_is_one=nblkflg_is_one+1
    1697                 :             :                              sumr=sumr+sym1_(idir1,idisy1,isym)*sym2_(idir2,idisy2,isym)*&
    1698                 :    40998657 : &                             d2(1,idisy1,ipesy1,idisy2,ipesy2)
    1699                 :             :                              sumi=sumi+sym1_(idir1,idisy1,isym)*sym2_(idir2,idisy2,isym)*&
    1700                 :    40998657 : &                             d2(2,idisy1,ipesy1,idisy2,ipesy2)
    1701                 :             : 
    1702                 :             : !                            Here, in case the symmetric of the element
    1703                 :             : !                            is the element, or the symmetric with
    1704                 :             : !                            respect to permutation of perturbations
    1705                 :             : !                            (some more conditions on the time-reversal
    1706                 :             : !                            symmetry must be fulfilled although)
    1707                 :             :                            else if(  idisy1==idir1 .and. ipesy1==ipert1&
    1708                 :             : &                             .and. idisy2==idir2 .and. ipesy2==ipert2&
    1709   [ +  +  +  +  :   232788957 : &                             .and.(isgn==1 .or. timrev==1 &
          +  +  +  +  +  
                      + ]
    1710                 :             : &                             .or. (idir1==idir2 .and. ipert1==ipert2)))&
    1711                 :             : &                             then
    1712                 :    58714582 :                              noccur=noccur+sym1_(idir1,idisy1,isym)*sym2_(idir2,idisy2,isym)
    1713                 :             :                            else if(  idisy1==idir2 .and. ipesy1==ipert2&
    1714                 :             : &                             .and. idisy2==idir1 .and. ipesy2==ipert1&
    1715   [ +  +  +  +  :   174074375 : &                             .and.(isgn==-1 .or. timrev==1&
          +  +  +  +  -  
                      + ]
    1716                 :             : &                             .or. (idir1==idir2 .and. ipert1==ipert2)))&
    1717                 :             : &                             then
    1718                 :    12296179 :                              noccur=noccur+sym1_(idir1,idisy1,isym)*sym2_(idir2,idisy2,isym)
    1719                 :             : 
    1720                 :             : !                            Here, electric field case
    1721                 :             :                            else if( exch12==1 .and. &
    1722                 :             : &                             ipert1==natom+2 .and. ipert2==natom+2&
    1723   [ +  +  +  +  :   161778196 : &                             .and.(( idisy1+idir1 ==3 &
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
                +  +  + ]
    1724                 :             : &                             .and. idisy2==3 .and. idir2==3)&
    1725                 :             : &                             .or. ( idisy1+idir2 ==3&
    1726                 :             : &                             .and. idisy2==3 .and. idir1==3)&
    1727                 :             : &                             .or. ( idisy2+idir2 ==3&
    1728                 :             : &                             .and. idisy1==3 .and. idir1==3)&
    1729                 :             : &                             .or. ( idisy2+idir1 ==3&
    1730                 :             : &                             .and. idisy1==3 .and. idir2==3)))&
    1731                 :             : &                             then
    1732                 :    15375656 :                              noccur=noccur+sym1_(idir1,idisy1,isym)*sym2_(idir2,idisy2,isym)
    1733                 :             : 
    1734                 :             :                            else
    1735                 :             : !                            Not found
    1736                 :             :                              found=0
    1737                 :             :                              quit=1
    1738                 :             :                              exit
    1739                 :             :                            end if
    1740                 :             : 
    1741                 :             :                          end if
    1742                 :             :                        end do
    1743         [ +  + ]:   505150042 :                        if(quit==1)exit
    1744                 :             :                      end do
    1745                 :             :                    end if
    1746                 :             : 
    1747                 :             : !                  In case zero_by_symm==0, the computed matrix element must be associated to at least one really computed matrix element
    1748         [ +  + ]:  1817957213 :                    if(zero_by_symm==0 .and. nblkflg_is_one==0)then
    1749                 :             :                      found=0
    1750                 :             :                    endif
    1751                 :             : 
    1752                 :             : !                  Now, if still found and associated to at least one really computed matrix element, put the correct value into array d2
    1753         [ +  + ]:  1817922749 :                    if(found==1)then
    1754                 :             : 
    1755                 :             : !                    In case of phonons, need to take into account the
    1756                 :             : !                    time-reversal symmetry, and the shift back to the unit cell
    1757                 :             : !
    1758                 :             : !                    XG990712 : I am not sure this must be kept for electric field ...
    1759                 :             : !                    1) Consider time-reversal symmetry
    1760                 :    59424462 :                      sumi=isgn*sumi
    1761                 :             : 
    1762   [ +  +  +  + ]:    59424462 :                      if(ipert1<=natom .and. ipert2<=natom)then
    1763                 :             : !                      2) Shift the atoms back to the unit cell.
    1764                 :             :                        arg1=two_pi*( qpt(1)*indsym(1,isym,ipert1)&
    1765                 :             : &                       +qpt(2)*indsym(2,isym,ipert1)&
    1766                 :      200134 : &                       +qpt(3)*indsym(3,isym,ipert1) )
    1767                 :             :                        arg2=two_pi*( qpt(1)*indsym(1,isym,ipert2)&
    1768                 :             : &                       +qpt(2)*indsym(2,isym,ipert2)&
    1769                 :      200134 : &                       +qpt(3)*indsym(3,isym,ipert2) )
    1770                 :      200134 :                        re=cos(arg1)*cos(arg2)+sin(arg1)*sin(arg2)
    1771                 :             : !                      XG010117 Must use isgn
    1772                 :      200134 :                        im=isgn*(cos(arg2)*sin(arg1)-cos(arg1)*sin(arg2))
    1773                 :             :                      else
    1774                 :             :                        re=one
    1775                 :             :                        im=zero
    1776                 :             :                      end if
    1777                 :             : 
    1778                 :             : !                    Final check, could still fail if the
    1779                 :             : !                    element was its own symmetric
    1780   [ +  +  -  + ]:    59424462 :                      if (abs(1.0_dp-re*noccur)< 1.0d-6.and.abs(im*noccur) <1.0d-6) then
    1781                 :             :                        found=0
    1782                 :             :                      end if
    1783                 :             : 
    1784                 :             :                    end if
    1785                 :             : 
    1786                 :             :                    if(found==1)then
    1787                 :             : 
    1788         [ +  + ]:      735490 :                      if(noccur==0)then
    1789                 :      600629 :                        d2(1,idir1,ipert1,idir2,ipert2)=re*sumr-im*sumi
    1790                 :      600629 :                        d2(2,idir1,ipert1,idir2,ipert2)=re*sumi+im*sumr
    1791                 :             :                      else
    1792                 :             : !                      See page July 2, 1994 in computer codes notebook
    1793                 :      134861 :                        xr=re*sumr-im*sumi
    1794                 :      134861 :                        xi=re*sumi+im*sumr
    1795                 :      134861 :                        norm=one+noccur**2-two*re*noccur
    1796                 :      134861 :                        xr=xr/norm
    1797                 :      134861 :                        xi=xi/norm
    1798                 :             :                        d2(1,idir1,ipert1,idir2,ipert2)=&
    1799                 :      134861 : &                       (one-re*noccur)*xr-im*noccur*xi
    1800                 :             :                        d2(2,idir1,ipert1,idir2,ipert2)=&
    1801                 :      134861 : &                       (one-re*noccur)*xi+im*noccur*xr
    1802                 :             :                      end if
    1803                 :             : 
    1804                 :             : !                    The element has been constructed !
    1805                 :      735490 :                      blkflg(idir1,ipert1,idir2,ipert2)=1
    1806                 :             : 
    1807                 :             :                      quit1=1
    1808                 :             :                      exit ! Exit loop on symmetry operations
    1809                 :             :                    end if
    1810                 :             : 
    1811                 :             : !                  End loop on all symmetries + time-reversal
    1812                 :             :                  end if
    1813                 :             :                end do
    1814                 :    56775539 :                if(quit1==1)exit
    1815                 :             :              end do
    1816                 :             : 
    1817                 :             :            end if
    1818                 :             :          end do ! End big loop on all elements
    1819                 :             :        end do
    1820                 :             :      end do
    1821                 :             :    end do
    1822                 :             : 
    1823                 :             :  end do !  End Big Big Loop
    1824                 :             : 
    1825                 :             : !MT oct. 20, 2014:
    1826                 :             : !Once the matrix has been built, it does not necessarily fulfill the correct symmetries.
    1827                 :             : !It has just been filled up from rows or columns that only fulfill symmetries preserving
    1828                 :             : !one particular perturbation.
    1829                 :             : !An additional symmetrization might solve this (do not consider TR-symmetry)
    1830                 :             :  if (do_final_sym) then
    1831         [ -  + ]:      174684 :    ABI_MALLOC(d2tmp1,(2,3,3))
    1832         [ -  + ]:      174684 :    ABI_MALLOC(d2tmp2,(2,3,3))
    1833   [ -  +  +  -  :      873420 :    ABI_MALLOC(d2work,(2,3,mpert,3,mpert))
          +  -  -  +  +  
          -  +  -  +  -  
             -  +  -  + ]
    1834   [ +  +  +  +  :    77429124 :    d2work(:,:,:,:,:)=d2(:,:,:,:,:)
          +  +  +  +  +  
                      + ]
    1835         [ +  + ]:      763944 :    do ipert1=1,mpert
    1836                 :             :    !do ipert1=1,min(natom+2,mpert)
    1837   [ +  +  +  +  :      589260 :      if ((ipert1==natom+1.or.ipert1==natom+10.or.ipert1==natom+11).or.(ipert1==natom+2.and.(.not.qzero))) cycle
          +  +  +  +  +  
                      + ]
    1838         [ +  + ]:      291642 :      if (ipert1<=natom)then
    1839                 :      214307 :        sym1_ => symrec
    1840                 :             :      else
    1841                 :       77335 :        sym1_ => symrel
    1842                 :             :      end if
    1843         [ +  + ]:     1894296 :      do ipert2=1,mpert
    1844                 :             :      !do ipert2=1,min(natom+2,mpert)
    1845                 :             : !      if (any(blkflg(:,ipert1,:,ipert2)==0)) cycle
    1846   [ +  +  +  +  :     1427970 :        if ((ipert2==natom+1.or.ipert2==natom+10.or.ipert2==natom+11).or.(ipert2==natom+2.and.(.not.qzero))) cycle
          +  +  +  +  +  
                      + ]
    1847         [ +  + ]:      913724 :        if (ipert2<=natom)then
    1848                 :      464462 :          sym2_ => symrec
    1849                 :             :        else
    1850                 :      449262 :          sym2_ => symrel
    1851                 :             :        end if
    1852                 :      913724 :        nsym_used=0
    1853   [ +  +  +  +  :    28325444 :        d2tmp2(:,:,:)=zero
                   +  + ]
    1854         [ +  + ]:    30622839 :        do isym=1,nsym
    1855         [ +  + ]:    30622839 :          if (symq(4,1,isym)==1) then
    1856         [ +  + ]:    16088356 :            ipesy1=ipert1;if (ipert1<=natom) ipesy1=indsym(4,isym,ipert1)
    1857         [ +  + ]:    16088356 :            ipesy2=ipert2;if (ipert2<=natom) ipesy2=indsym(4,isym,ipert2)
    1858                 :             : !          The condition on next line is too severe, since some elements of sym1_ or sym2_ might be zero,
    1859                 :             : !          which means not all blkflg(:,ipesy1,:,ipesy2) would need to be 1 to symmetrize the matrix.
    1860                 :             : !          However, coding something more refined is really more difficult.
    1861                 :             : !          This condition then has the side effect that more symmetries can be applied when zero_by_symm==1,
    1862                 :             : !          since blkflg can be set to 1 when the symmetries guarantee the matrix element to be zero.
    1863   [ +  +  +  +  :    82420363 :            if (all(blkflg(:,ipesy1,:,ipesy2)==1)) then
             +  +  +  + ]
    1864                 :     5524728 :              nsym_used=nsym_used+1
    1865                 :     5524728 :              re=one;im=zero
    1866   [ +  +  +  +  :     5524728 :              if (ipert1<=natom.and.ipert2<=natom.and.(.not.qzero)) then
                   +  + ]
    1867                 :             :                arg1=two_pi*(qpt(1)*(indsym(1,isym,ipert1)-indsym(1,isym,ipert2)) &
    1868                 :             : &                          +qpt(2)*(indsym(2,isym,ipert1)-indsym(2,isym,ipert2)) &
    1869                 :     2626726 : &                          +qpt(3)*(indsym(3,isym,ipert1)-indsym(3,isym,ipert2)))
    1870                 :     2626726 :                re=cos(arg1);im=sin(arg1)
    1871                 :             :              end if
    1872   [ +  +  +  +  :   171266568 :              d2tmp1(:,:,:)=zero
                   +  + ]
    1873         [ +  + ]:    22098912 :              do idir2=1,3 !kappa
    1874         [ +  + ]:    71821464 :                do idir1=1,3 !mu
    1875         [ +  + ]:   215464392 :                  do idisy1=1,3 !nu
    1876                 :             :                    d2tmp1(:,idir1,idir2)=d2tmp1(:,idir1,idir2) &
    1877         [ +  + ]:   497225520 : &                     +sym1_(idir1,idisy1,isym)*d2(:,idisy1,ipesy1,idir2,ipesy2)
    1878                 :             :                  end do
    1879                 :             :                end do
    1880                 :             :              end do
    1881         [ +  + ]:    22098912 :              do idir2=1,3 !mu
    1882         [ +  + ]:    71821464 :                do idir1=1,3 !kappa
    1883         [ +  + ]:   215464392 :                  do idisy2=1,3 !nu
    1884                 :             :                    d2tmp2(1,idir1,idir2)=d2tmp2(1,idir1,idir2) &
    1885                 :   149167656 : &                  +sym2_(idir2,idisy2,isym)*(d2tmp1(1,idir1,idisy2)*re-d2tmp1(2,idir1,idisy2)*im)
    1886                 :             :                    d2tmp2(2,idir1,idir2)=d2tmp2(2,idir1,idir2) &
    1887                 :   198890208 : &                  +sym2_(idir2,idisy2,isym)*(d2tmp1(1,idir1,idisy2)*im+d2tmp1(2,idir1,idisy2)*re)
    1888                 :             :                  end do
    1889                 :             :                end do
    1890                 :             :              end do
    1891                 :             :            end if
    1892                 :             :          end if
    1893                 :             :        end do ! isym
    1894   [ +  +  +  +  :    10898324 :        if (nsym_used>0) d2work(:,1:3,ipert1,1:3,ipert2)=d2tmp2(:,1:3,1:3)/dble(nsym_used)
             +  +  +  + ]
    1895                 :             :      end do !ipert2
    1896                 :             :    end do !ipert1
    1897   [ +  -  +  +  :    10401242 :    if (mpert>=natom)   d2(:,1:3,1:natom,1:3,1:natom)=d2work(:,1:3,1:natom,1:3,1:natom)
          +  +  +  +  +  
                +  +  + ]
    1898         [ +  + ]:      174684 :    if (mpert>=natom+2) then
    1899   [ +  +  +  +  :     6801655 :      d2(:,1:3,natom+2,1:3,1:natom)=d2work(:,1:3,natom+2,1:3,1:natom)
             +  +  +  + ]
    1900   [ +  +  +  +  :     7111206 :      d2(:,1:3,1:natom,1:3,natom+2)=d2work(:,1:3,1:natom,1:3,natom+2)
             +  +  +  + ]
    1901   [ +  +  +  +  :     5407764 :      d2(:,1:3,natom+2,1:3,natom+2)=d2work(:,1:3,natom+2,1:3,natom+2)
                   +  + ]
    1902                 :             :    end if
    1903         [ -  + ]:      174684 :    ABI_FREE(d2tmp1)
    1904         [ -  + ]:      174684 :    ABI_FREE(d2tmp2)
    1905         [ -  + ]:      174684 :    ABI_FREE(d2work)
    1906                 :             :  end if
    1907                 :             : 
    1908         [ +  + ]:      174684 : end subroutine d2sym3
    1909                 :             : !!***
    1910                 :             : 
    1911                 :             : !----------------------------------------------------------------------
    1912                 :             : 
    1913                 :             : !!****f* m_dynmat/q0dy3_apply
    1914                 :             : !! NAME
    1915                 :             : !! q0dy3_apply
    1916                 :             : !!
    1917                 :             : !! FUNCTION
    1918                 :             : !! Takes care of the inclusion of the ewald q=0 term in the dynamical
    1919                 :             : !! matrix - corrects the dyew matrix provided as input
    1920                 :             : !! See Eq.(71) in Gonze&Lee PRB 55, 10355 (1997) [[cite:Gonze1997a]],
    1921                 :             : !! get the left hand side.
    1922                 :             : !!
    1923                 :             : !! INPUTS
    1924                 :             : !!  dyewq0(3,3,natom) = part needed to correct the dynamical matrix for atom self-interaction.
    1925                 :             : !!  natom= number of atom in the unit cell
    1926                 :             : !!
    1927                 :             : !! SIDE EFFECTS
    1928                 :             : !!  dyew(2,3,natom,3,natom)= dynamical matrix corrected on output
    1929                 :             : !!
    1930                 :             : !! NOTES
    1931                 :             : !! Should be used just after each call to dfpt_ewald, for both
    1932                 :             : !! q==0 and the real wavelength.
    1933                 :             : !!
    1934                 :             : !! The q0dy3_apply should be used in conjunction with the subroutine dfpt_ewald (or ewald9):
    1935                 :             : !! First, the call of dfpt_ewald with q==0 should be done,
    1936                 :             : !!   then the call to q0dy3_calc will produce
    1937                 :             : !!   the dyewq0 matrix from the (q=0) dyew matrix
    1938                 :             : !! Second, the call of dfpt_ewald with the real q (either =0 or diff 0)
    1939                 :             : !!   should be done, then the call to q0dy3_apply
    1940                 :             : !!   will produce the correct dynamical matrix dyew starting from
    1941                 :             : !!   the previously calculated dyewq0 and the bare(non-corrected)
    1942                 :             : !!   dyew matrix
    1943                 :             : !!
    1944                 :             : !! SOURCE
    1945                 :             : 
    1946                 :      176025 : subroutine q0dy3_apply(natom,dyewq0,dyew)
    1947                 :             : 
    1948                 :             : !Arguments -------------------------------
    1949                 :             : !scalars
    1950                 :             :  integer,intent(in) :: natom
    1951                 :             : !arrays
    1952                 :             :  real(dp),intent(in) :: dyewq0(3,3,natom)
    1953                 :             :  real(dp),intent(inout) :: dyew(2,3,natom,3,natom)
    1954                 :             : 
    1955                 :             : !Local variables -------------------------
    1956                 :             : !scalars
    1957                 :             :  integer :: ia,mu,nu
    1958                 :             : ! *********************************************************************
    1959                 :             : 
    1960         [ +  + ]:      704100 :  do mu=1,3
    1961         [ +  + ]:     2288325 :    do nu=1,3
    1962         [ +  + ]:     5640615 :      do ia=1,natom
    1963                 :     5112540 :        dyew(1,mu,ia,nu,ia)=dyew(1,mu,ia,nu,ia)-dyewq0(mu,nu,ia)
    1964                 :             :      end do
    1965                 :             :    end do
    1966                 :             :  end do
    1967                 :             : 
    1968                 :      176025 : end subroutine q0dy3_apply
    1969                 :             : !!***
    1970                 :             : 
    1971                 :             : !----------------------------------------------------------------------
    1972                 :             : 
    1973                 :             : !!****f* m_dynmat/q0dy3_calc
    1974                 :             : !! NAME
    1975                 :             : !! q0dy3_calc
    1976                 :             : !!
    1977                 :             : !! FUNCTION
    1978                 :             : !! Calculate the q=0 correction term to the dynamical matrix
    1979                 :             : !! See Eq.(71) in Gonze&Lee PRB 55, 10355 (1997) [[cite:Gonze1997a]], the sum over \kappa"
    1980                 :             : !!
    1981                 :             : !! INPUTS
    1982                 :             : !!  dyew(2,3,natom,3,natom)= dynamical matrix
    1983                 :             : !!    input, non-corrected, for q=0 if option=1 or 2
    1984                 :             : !!  natom= number of atom in the unit cell
    1985                 :             : !!  option= either 1 or 2:
    1986                 :             : !!     1: use dyew to calculate dyewq0 symmetrical form
    1987                 :             : !!     2: use dyew to calculate dyewq0 symmetrical form
    1988                 :             : !!
    1989                 :             : !! OUTPUT
    1990                 :             : !!  dyewq0(3,3,natom) = part needed to correct
    1991                 :             : !!    the dynamical matrix for atom self-interaction.
    1992                 :             : !!
    1993                 :             : !! NOTES
    1994                 :             : !! Should be used just after each call to dfpt_ewald, for both
    1995                 :             : !! q==0 and the real wavelength.
    1996                 :             : !!
    1997                 :             : !! If option=1 or 2, q0dy3_calc uses an Ewald dynamical matrix at q=0,
    1998                 :             : !! called dyew, to produce a contracted form called dyewq0 :
    1999                 :             : !! either:
    2000                 :             : !!   in an unsymmetrical form (if option=1), or
    2001                 :             : !!   in a symmetrical form (if option=2).
    2002                 :             : !!
    2003                 :             : !! The q0dy3_calc should be used in conjunction with the subroutine dfpt_ewald (or ewald9).
    2004                 :             : !! First, the call of dfpt_ewald with q==0 should be done ,
    2005                 :             : !!   then the call to q0dy3_calc will produce
    2006                 :             : !!   the dyewq0 matrix from the (q=0) dyew matrix
    2007                 :             : !! Second, the call of dfpt_ewald with the real q (either =0 or diff 0)
    2008                 :             : !!   should be done, then the call to q0dy3_apply
    2009                 :             : !!   will produce the correct dynamical matrix dyew starting from
    2010                 :             : !!   the previously calculated dyewq0 and the bare(non-corrected)
    2011                 :             : !!   dyew matrix
    2012                 :             : !!
    2013                 :             : !! SOURCE
    2014                 :             : 
    2015                 :         609 : subroutine q0dy3_calc(natom,dyewq0,dyew,option)
    2016                 :             : 
    2017                 :             : !Arguments -------------------------------
    2018                 :             : !scalars
    2019                 :             :  integer,intent(in) :: natom,option
    2020                 :             : !arrays
    2021                 :             :  real(dp),intent(in) :: dyew(2,3,natom,3,natom)
    2022                 :             :  real(dp),intent(out) :: dyewq0(3,3,natom)
    2023                 :             : 
    2024                 :             : !Local variables -------------------------
    2025                 :             : !scalars
    2026                 :             :  integer :: ia,ib,mu,nu
    2027                 :             :  character(len=500) :: msg
    2028                 :             : ! *********************************************************************
    2029                 :             : 
    2030         [ +  - ]:         609 :  if(option==1.or.option==2.or.option==6)then
    2031         [ +  + ]:        2436 :    do mu=1,3
    2032         [ +  + ]:        7917 :      do nu=1,3
    2033         [ +  + ]:       19467 :        do ia=1,natom
    2034                 :       12159 :          dyewq0(mu,nu,ia)=zero
    2035         [ +  + ]:       56349 :          do ib=1,natom
    2036                 :       50868 :            dyewq0(mu,nu,ia)=dyewq0(mu,nu,ia)+dyew(1,mu,ia,nu,ib)
    2037                 :             :          end do
    2038                 :             :        end do
    2039                 :             :      end do
    2040                 :             :    end do
    2041                 :             :  else
    2042                 :             :    write (msg, '(3a)')&
    2043                 :           0 : &   'option should be 1 or 2 or 6.',ch10,&
    2044                 :           0 : &   'action: correct calling routine'
    2045                 :           0 :    ABI_BUG(msg)
    2046                 :             :  end if
    2047                 :             : 
    2048         [ +  + ]:         609 :  if(option==2)then
    2049         [ +  + ]:         141 :    do ia=1,natom
    2050         [ +  + ]:         477 :      do mu=1,3
    2051         [ +  + ]:        1120 :        do nu=mu,3
    2052                 :         672 :          dyewq0(mu,nu,ia)=(dyewq0(mu,nu,ia)+dyewq0(nu,mu,ia))/2
    2053                 :        1008 :          dyewq0(nu,mu,ia)=dyewq0(mu,nu,ia)
    2054                 :             :        end do
    2055                 :             :      end do
    2056                 :             :    end do
    2057                 :             :  end if
    2058                 :             : 
    2059                 :         609 : end subroutine q0dy3_calc
    2060                 :             : !!***
    2061                 :             : 
    2062                 :             : !----------------------------------------------------------------------
    2063                 :             : 
    2064                 :             : !!****f* m_dynmat/symdyma
    2065                 :             : !!
    2066                 :             : !! NAME
    2067                 :             : !! symdyma
    2068                 :             : !!
    2069                 :             : !! FUNCTION
    2070                 :             : !! Symmetrize the dynamical matrices
    2071                 :             : !!
    2072                 :             : !! INPUTS
    2073                 :             : !! indsym(4,nsym*natom)=indirect indexing array : for each
    2074                 :             : !!   isym,iatom, fourth element is label of atom into which iatom is sent by
    2075                 :             : !!   INVERSE of symmetry operation isym; first three elements are the primitive
    2076                 :             : !!   translations which must be subtracted after the transformation to get back
    2077                 :             : !!   to the original unit cell.
    2078                 :             : !! natom=number of atoms in unit cell
    2079                 :             : !! nsym=number of space group symmetries
    2080                 :             : !! qptn(3)=normalized phonon wavevector
    2081                 :             : !! rprimd(3,3)=dimensional primitive translations (bohr)
    2082                 :             : !! symrel(3,3,nsym)=3x3 matrices of the group symmetries (real space)
    2083                 :             : !!
    2084                 :             : !! SIDE EFFECTS
    2085                 :             : !! Input/Output
    2086                 :             : !! dmati(2*3*natom*3*natom)=dynamical matrices in cartesian coordinates relative to the q
    2087                 :             : !!  points of the B.Z. sampling
    2088                 :             : !!
    2089                 :             : !! NOTES
    2090                 :             : !! the procedure of the symmetrization of the dynamical matrix follows the
    2091                 :             : !! equations in: Hendrikse et al., Computer Phys. Comm. 86, 297 (1995) [[cite:Hendrikse1995]]
    2092                 :             : !!
    2093                 :             : !! TODO
    2094                 :             : !! A full description of the equations should be included
    2095                 :             : !!
    2096                 :             : !! SOURCE
    2097                 :             : 
    2098                 :      217641 : subroutine symdyma(dmati,indsym,natom,nsym,qptn,rprimd,symrel,symafm)
    2099                 :             : 
    2100                 :             : !Arguments -------------------------------
    2101                 :             : !scalars
    2102                 :             :  integer,intent(in) :: natom,nsym
    2103                 :             : !arrays
    2104                 :             :  integer,intent(in) :: indsym(4,nsym,natom),symrel(3,3,nsym)
    2105                 :             :  integer,intent(in) :: symafm(nsym)
    2106                 :             :  real(dp),intent(in) :: qptn(3),rprimd(3,3)
    2107                 :             :  real(dp),intent(inout) :: dmati(2*3*natom*3*natom)
    2108                 :             : 
    2109                 :             : !Local variables -------------------------
    2110                 :             : !scalars
    2111                 :             :  integer :: i1,i2,iat,idir,ii,index,isgn,isym,itirev,jat,jdir,jj,kk,ll
    2112                 :             :  integer :: niat,njat,timrev
    2113                 :             :  real(dp) :: arg1,arg2,dmint,im,re,sumi,sumr
    2114                 :             : !arrays
    2115                 :      435282 :  integer :: indij(natom,natom),symq(4,2,nsym),symrec(3,3,nsym)
    2116                 :      435282 :  real(dp) :: TqR(3,3),TqS_(3,3),dynmat(2,3,natom,3,natom)
    2117                 :      435282 :  real(dp) :: dynmatint(2*nsym,2,3,natom,3,natom),gprimd(3,3)
    2118                 :      435282 :  real(dp) :: symcart(3,3,nsym)
    2119                 :             : ! *********************************************************************
    2120                 :             : !FIXME Disabling optimization with NVHPC in this routine
    2121                 :             : !      because of significant numerical divergence
    2122                 :             : !nvf$r opt=0
    2123                 :             : 
    2124                 :             :  ! 0) initializations
    2125                 :      217641 :  call matr3inv(rprimd,gprimd)
    2126         [ +  + ]:     6602262 :  do isym=1,nsym
    2127                 :     6602262 :    call mati3inv(symrel(:,:,isym),symrec(:,:,isym))
    2128                 :             :  end do
    2129                 :             : 
    2130                 :             :  TqR=zero
    2131                 :             :  TqS_=zero
    2132   [ +  +  +  +  :    36313397 :  dynmat=zero
          +  +  +  +  +  
                      + ]
    2133                 :             : 
    2134                 :             : !Note: dynmat is used as work space here
    2135                 :             :  i1=0
    2136         [ +  + ]:      621755 :  do iat=1,natom
    2137         [ +  + ]:     1834097 :    do idir=1,3
    2138                 :     1212342 :      i1=i1+1
    2139                 :     1212342 :      i2=0
    2140         [ +  + ]:     5064386 :      do jat=1,natom
    2141         [ +  + ]:    15004062 :        do jdir=1,3
    2142                 :    10343790 :          i2=i2+1
    2143                 :    10343790 :          index=i1+3*natom*(i2-1)
    2144                 :    10343790 :          dynmat(1,idir,iat,jdir,jat)=dmati(2*index-1)
    2145                 :    13791720 :          dynmat(2,idir,iat,jdir,jat)=dmati(2*index  )
    2146                 :             :        end do
    2147                 :             :      end do
    2148                 :             :    end do
    2149                 :             :  end do
    2150                 :             : 
    2151                 :             : !Transform symrel to cartesian coordinates (RC coding)
    2152                 :             : !do isym=1,nsym
    2153                 :             : !symcart(:,:,isym)=matmul(rprimd,matmul(dble(symrel(:,:,isym)),gprimd))
    2154                 :             : !end do
    2155                 :             : 
    2156                 :             : !Coding from symdm9
    2157         [ +  + ]:     6602262 :  do isym=1,nsym
    2158         [ +  + ]:    25756125 :    do jj=1,3
    2159         [ +  + ]:    76615452 :      symcart(:,jj,isym)=zero
    2160         [ +  + ]:    83000073 :      do kk=1,3
    2161         [ +  + ]:   249000219 :        do ll=1,3
    2162         [ +  + ]:   747000657 :          symcart(:,jj,isym)=symcart(:,jj,isym)+rprimd(:,kk)*gprimd(jj,ll)*symrel(kk,ll,isym)
    2163                 :             :        end do
    2164                 :             :      end do
    2165                 :             :    end do
    2166                 :             :  end do
    2167                 :             : 
    2168                 :             :  ! Get the symq of the CURRENT Q POINT
    2169                 :             :  ! mjv: set prtvol=0 for production runs.
    2170                 :      217641 :  call littlegroup_q(nsym,qptn,symq,symrec,symafm,timrev,prtvol=0)
    2171                 :             : 
    2172   [ +  +  +  + ]:     1771065 :  indij(:,:)=0
    2173   [ +  +  +  +  :   787866065 :  dynmatint=zero
          +  +  +  +  +  
                +  +  + ]
    2174                 :             : 
    2175         [ +  + ]:     6602262 :  do isym=1,nsym  ! loop over all the symmetries
    2176                 :             :    ! write(std_out,*) 'current symmetry',isym
    2177         [ +  + ]:    19371504 :    do itirev=1,2  ! loop over the time-reversal symmetry
    2178                 :    12769242 :      isgn=3-2*itirev
    2179                 :             :      ! write(std_out,*) 'timereversal',isgn
    2180                 :             : 
    2181         [ +  + ]:    19153863 :      if (symq(4,itirev,isym)==1) then ! isym belongs to the wave vector point group
    2182                 :             :        ! write(std_out,*) 'isym belongs to the wave vector point group'
    2183         [ +  + ]:     2284327 :        do iat=1,natom
    2184         [ +  + ]:     6439459 :          do jat=1,natom
    2185                 :     4155132 :            niat=indsym(4,isym,iat)  ! niat={R|t}iat
    2186                 :     4155132 :            njat=indsym(4,isym,jat)  ! njat={R|t}jat
    2187                 :     4155132 :            indij(niat,njat)=indij(niat,njat)+1
    2188                 :             :            ! write(std_out,'(a,5i5)') 'current status:',iat,jat,niat,njat,indij(niat,njat)
    2189                 :             :            ! phase calculation, arg1 and arg2 because of two-atom derivative
    2190                 :             :            arg1=two_pi*( qptn(1)*indsym(1,isym,iat)+&
    2191                 :             :              qptn(2)*indsym(2,isym,iat)+&
    2192                 :     4155132 :              qptn(3)*indsym(3,isym,iat) )
    2193                 :             :            arg2=two_pi*( qptn(1)*indsym(1,isym,jat)+&
    2194                 :             :              qptn(2)*indsym(2,isym,jat)+&
    2195                 :     4155132 :              qptn(3)*indsym(3,isym,jat) )
    2196                 :             : 
    2197                 :     4155132 :            re=cos(arg1)*cos(arg2)+sin(arg1)*sin(arg2)
    2198                 :     4155132 :            im=isgn*(cos(arg2)*sin(arg1)-cos(arg1)*sin(arg2))
    2199                 :             : 
    2200         [ +  + ]:    18111826 :            do idir=1,3     ! loop over displacements
    2201         [ +  + ]:    54016716 :              do jdir=1,3   ! loop over displacements
    2202                 :             :                ! we pick the (iat,jat) (3x3) block of the dyn.mat.
    2203                 :             :                sumr=zero
    2204                 :             :                sumi=zero
    2205         [ +  + ]:   149584752 :                do ii=1,3
    2206         [ +  + ]:   486150444 :                  do jj=1,3
    2207                 :   336565692 :                    sumr=sumr+symcart(idir,ii,isym)*dynmat(1,ii,niat,jj,njat)*symcart(jdir,jj,isym)
    2208                 :   448754256 :                    sumi=sumi+symcart(idir,ii,isym)*dynmat(2,ii,niat,jj,njat)*symcart(jdir,jj,isym)
    2209                 :             :                  end do
    2210                 :             :                end do
    2211                 :    37396188 :                sumi=isgn*sumi
    2212                 :             : 
    2213                 :    37396188 :                dynmatint(nsym*(itirev-1)+isym,1,idir,iat,jdir,jat)=re*sumr-im*sumi
    2214                 :    49861584 :                dynmatint(nsym*(itirev-1)+isym,2,idir,iat,jdir,jat)=re*sumi+im*sumr
    2215                 :             :              end do
    2216                 :             :            end do
    2217                 :             :          end do
    2218                 :             :        end do ! end treatment of the (iat,jat) (3x3) block of dynmat
    2219                 :             :      end if ! symmetry check
    2220                 :             :    end do ! time-reversal
    2221                 :             :  end do ! symmetries
    2222                 :             : 
    2223                 :             :  !4) make the average, get the final symmetric dynamical matrix
    2224         [ +  + ]:      621755 :  do iat=1,natom
    2225         [ +  + ]:     1771065 :    do jat=1,natom
    2226         [ +  + ]:     5001354 :      do idir=1,3
    2227         [ +  + ]:    14941030 :        do jdir=1,3
    2228                 :             :          dmint=zero
    2229         [ +  + ]:   386120124 :          do isym=1,2*nsym
    2230                 :   386120124 :            dmint=dmint+dynmatint(isym,1,idir,iat,jdir,jat)
    2231                 :             :          end do
    2232                 :    10343790 :          dynmat(1,idir,iat,jdir,jat)=dmint/dble(indij(iat,jat))
    2233                 :    10343790 :          dmint=zero
    2234         [ +  + ]:   386120124 :          do isym=1,2*nsym
    2235                 :   386120124 :            dmint=dmint+dynmatint(isym,2,idir,iat,jdir,jat)
    2236                 :             :          end do
    2237                 :    13791720 :          dynmat(2,idir,iat,jdir,jat)=dmint/dble(indij(iat,jat))
    2238                 :             :        end do
    2239                 :             :      end do
    2240                 :             :    end do
    2241                 :             :  end do
    2242                 :             : 
    2243                 :             :  i1=0
    2244         [ +  + ]:      621755 :  do iat=1,natom
    2245         [ +  + ]:     1834097 :    do idir=1,3
    2246                 :     1212342 :      i1=i1+1
    2247                 :     1212342 :      i2=0
    2248         [ +  + ]:     5064386 :      do jat=1,natom
    2249         [ +  + ]:    15004062 :        do jdir=1,3
    2250                 :    10343790 :          i2=i2+1
    2251                 :    10343790 :          index=i1+3*natom*(i2-1)
    2252                 :    10343790 :          dmati(2*index-1)=dynmat(1,idir,iat,jdir,jat)
    2253                 :    13791720 :          dmati(2*index  )=dynmat(2,idir,iat,jdir,jat)
    2254                 :             :        end do
    2255                 :             :      end do
    2256                 :             :    end do
    2257                 :             :  end do
    2258                 :             : 
    2259                 :      217641 : end subroutine symdyma
    2260                 :             : !!***
    2261                 :             : 
    2262                 :             : !!****f* m_dynmat/dfpt_sygra
    2263                 :             : !!
    2264                 :             : !! NAME
    2265                 :             : !! dfpt_sygra
    2266                 :             : !!
    2267                 :             : !! FUNCTION
    2268                 :             : !! Symmetrize derivatives of energy with respect to coordinates,
    2269                 :             : !! as appearing in phonon calculations.
    2270                 :             : !! Unsymmetrized gradients are input as deunsy; symmetrized grads are then placed in desym.
    2271                 :             : !! If nsym=1 simply copy deunsy into desym (only symmetry is identity).
    2272                 :             : !! The index of the initial perturbation is needed, in case there is a change
    2273                 :             : !! of atom position (moved in another cell) due to the symmetry operation.
    2274                 :             : !!
    2275                 :             : !! INPUTS
    2276                 :             : !!  natom=number of atoms in cell
    2277                 :             : !!  deunsy(2,3,natom)=unsymmetrized gradients wrt dimensionless tn (hartree)
    2278                 :             : !!  note: there is a real and a imaginary part ...
    2279                 :             : !!  indsym(4,nsym,natom)=label given by subroutine symatm, indicating atom
    2280                 :             : !!   label which gets rotated into given atom by given symmetry
    2281                 :             : !!   (first three elements are related primitive translation--
    2282                 :             : !!   see symatm where this is computed)
    2283                 :             : !!  nsym=number of symmetry operators in group
    2284                 :             : !!  ipert=index of the initial perturbation
    2285                 :             : !!  qpt(3)= wavevector of the phonon, in reduced coordinates
    2286                 :             : !!  symrec(3,3,nsym)=symmetries of group in terms of operations on
    2287                 :             : !!    reciprocal space primitive translations--see comments below
    2288                 :             : !!
    2289                 :             : !! OUTPUT
    2290                 :             : !! desym(2,3,natom)=symmetrized gradients wrt dimensionless tn (hartree)
    2291                 :             : !!
    2292                 :             : !! NOTES
    2293                 :             : !! Written by X. Gonze starting from sygrad, written by D.C. Allan:
    2294                 :             : !!    introduction of the q vector for phonon symmetrization
    2295                 :             : !! This routine should once be merged with sygrad...
    2296                 :             : !!
    2297                 :             : !! SOURCE
    2298                 :             : 
    2299                 :        2549 : subroutine dfpt_sygra(natom,desym,deunsy,indsym,ipert,nsym,qpt,symrec)
    2300                 :             : 
    2301                 :             : !Arguments -------------------------------
    2302                 :             : !scalars
    2303                 :             :  integer,intent(in) :: ipert,natom,nsym
    2304                 :             : !arrays
    2305                 :             :  integer,intent(in) :: indsym(4,nsym,natom),symrec(3,3,nsym)
    2306                 :             :  real(dp),intent(in) :: deunsy(2,3,natom),qpt(3)
    2307                 :             :  real(dp),intent(out) :: desym(2,3,natom)
    2308                 :             : 
    2309                 :             : !Local variables -------------------------
    2310                 :             : !scalars
    2311                 :             :  integer :: ia,ind,isym,mu
    2312                 :             :  real(dp) :: arg,im,re,sumi,sumr
    2313                 :             : ! *********************************************************************
    2314                 :             : 
    2315         [ +  + ]:        2549 :  if (nsym==1) then
    2316                 :             : 
    2317                 :             : !  Only symmetry is identity so simply copy
    2318   [ +  +  +  +  :       46002 :    desym(:,:,:)=deunsy(:,:,:)
                   +  + ]
    2319                 :             : 
    2320                 :             :  else
    2321                 :             : 
    2322                 :             : !  Actually conduct symmetrization
    2323                 :             : !  write(std_out,*)' dfpt_sygra : desym(:2,:3,:natom),qpt(:)',desym(:2,:3,:natom),qpt(:)
    2324         [ +  + ]:        2269 :    do ia=1,natom
    2325                 :             : !    write(std_out,*)' dfpt_sygra : ia=',ia
    2326         [ +  + ]:        7135 :      do mu=1,3
    2327                 :             :        sumr=zero
    2328                 :             :        sumi=zero
    2329                 :             : !      write(std_out,*)' dfpt_sygra : mu=',mu
    2330         [ +  + ]:       23904 :        do isym=1,nsym
    2331                 :       19038 :          ind=indsym(4,isym,ia)
    2332                 :             : !        Must shift the atoms back to the unit cell.
    2333                 :             : !        arg=two_pi*( qpt(1)*indsym(1,isym,ia)&
    2334                 :             : !        &         +qpt(2)*indsym(2,isym,ia)&
    2335                 :             : !        &         +qpt(3)*indsym(3,isym,ia) )
    2336                 :             : !        Selection of non-zero q point, to avoid ipert being outside the 1 ... natom range
    2337         [ +  + ]:       19038 :          if(qpt(1)**2+qpt(2)**2+qpt(3)**2 > tol16)then
    2338                 :             :            arg=two_pi*( qpt(1)*(indsym(1,isym,ia)-indsym(1,isym,ipert))&
    2339                 :             : &           +qpt(2)* (indsym(2,isym,ia)-indsym(2,isym,ipert))&
    2340                 :        1896 : &           +qpt(3)* (indsym(3,isym,ia)-indsym(3,isym,ipert)))
    2341                 :             :          else
    2342                 :             :            arg=zero
    2343                 :             :          end if
    2344                 :             : 
    2345                 :             :          re=dble(symrec(mu,1,isym))*deunsy(1,1,ind)+&
    2346                 :             : &         dble(symrec(mu,2,isym))*deunsy(1,2,ind)+&
    2347                 :       19038 : &         dble(symrec(mu,3,isym))*deunsy(1,3,ind)
    2348                 :             :          im=dble(symrec(mu,1,isym))*deunsy(2,1,ind)+&
    2349                 :             : &         dble(symrec(mu,2,isym))*deunsy(2,2,ind)+&
    2350                 :       19038 : &         dble(symrec(mu,3,isym))*deunsy(2,3,ind)
    2351                 :       19038 :          sumr=sumr+re*cos(arg)-im*sin(arg)
    2352                 :       23904 :          sumi=sumi+re*sin(arg)+im*cos(arg)
    2353                 :             : !        sumr=sumr+re
    2354                 :             : !        sumi=sumi+im
    2355                 :             : !        write(std_out,*)' dfpt_sygra : isym,indsym(4,isym,ia),arg,re,im,sumr,sumi',&
    2356                 :             : !        &      isym,indsym(4,isym,ia),arg,re,im,sumr,sumi
    2357                 :             :        end do
    2358                 :        4866 :        desym(1,mu,ia)=sumr/dble(nsym)
    2359                 :        6488 :        desym(2,mu,ia)=sumi/dble(nsym)
    2360                 :             : !      write(std_out,*)' dfpt_sygra : desym(:,mu,ia)',desym(:,mu,ia)
    2361                 :             :      end do
    2362                 :             :    end do
    2363                 :             :  end if
    2364                 :             : 
    2365                 :        2549 : end subroutine dfpt_sygra
    2366                 :             : !!***
    2367                 :             : 
    2368                 :             : !!****f* m_dynmat/dfpt_sydy
    2369                 :             : !! NAME
    2370                 :             : !! dfpt_sydy
    2371                 :             : !!
    2372                 :             : !! FUNCTION
    2373                 :             : !! Symmetrize dynamical matrix (eventually diagonal wrt to the atoms)
    2374                 :             : !! Unsymmetrized dynamical matrix is input as dyfrow;
    2375                 :             : !! symmetrized dynamical matrix is then placed in sdyfro.
    2376                 :             : !! If nsym=1 simply copy dyfrow into sdyfro.
    2377                 :             : !!
    2378                 :             : !! INPUTS
    2379                 :             : !!  cplex=1 if dynamical matrix is real, 2 if it is complex
    2380                 :             : !!  dyfrow(3,3,natom,1+(natom-1)*nondiag)=unsymmetrized dynamical matrix
    2381                 :             : !!  indsym(4,msym*natom)=indirect indexing array: for each
    2382                 :             : !!   isym,iatom, fourth element is label of atom into which iatom is sent by
    2383                 :             : !!   INVERSE of symmetry operation isym; first three elements are the primitive
    2384                 :             : !!   translations which must be subtracted after the transformation to get back
    2385                 :             : !!   to the original unit cell.
    2386                 :             : !!  natom=number of atoms in cell.
    2387                 :             : !!  nondiag=0 if dynamical matrix is     diagonal with respect to atoms
    2388                 :             : !           1 if dynamical matrix is non diagonal with respect to atoms
    2389                 :             : !!  nsym=number of symmetry operators in group.
    2390                 :             : !!  qphon(3)=wavevector of the phonon
    2391                 :             : !!  symq(4,2,nsym)=1 if symmetry preserves present qpoint. From littlegroup_q
    2392                 :             : !!  symrec(3,3,nsym)=symmetries of group in terms of operations on real
    2393                 :             : !!    space primitive translations (integers).
    2394                 :             : !!
    2395                 :             : !! OUTPUT
    2396                 :             : !!  sdyfro(3,3,natom,1+(natom-1)*nondiag)=symmetrized dynamical matrix
    2397                 :             : !!
    2398                 :             : !! NOTES
    2399                 :             : !! Symmetrization of gradients with respect to reduced
    2400                 :             : !! coordinates tn is conducted according to the expression
    2401                 :             : !! $[d(e)/d(t(n,a))]_{symmetrized} = (1/Nsym)*Sum(S)*symrec(n,m,S)*
    2402                 :             : !!              [d(e)/d(t(m,b))]_{unsymmetrized}$
    2403                 :             : !! where $t(m,b)= (symrel^{-1})(m,n)*(t(n,a)-tnons(n))$ and tnons
    2404                 :             : !! is a possible nonsymmorphic translation.  The label "b" here
    2405                 :             : !! refers to the atom which gets rotated into "a" under symmetry "S".
    2406                 :             : !! symrel is the symmetry matrix in real space, which is the inverse
    2407                 :             : !! transpose of symrec.  symrec is the symmetry matrix in reciprocal
    2408                 :             : !! space.  $sym_{cartesian} = R * symrel * R^{-1} = G * symrec * G^{-1}$
    2409                 :             : !! where the columns of R and G are the dimensional primitive translations
    2410                 :             : !! in real and reciprocal space respectively.
    2411                 :             : !! Note the use of "symrec" in the symmetrization expression above.
    2412                 :             : !!
    2413                 :             : !! SOURCE
    2414                 :             : 
    2415                 :        1353 : subroutine dfpt_sydy(cplex,dyfrow,indsym,natom,nondiag,nsym,qphon,sdyfro,symq,symrec)
    2416                 :             : 
    2417                 :             : !Arguments -------------------------------
    2418                 :             : !scalars
    2419                 :             :  integer,intent(in) :: cplex,natom,nondiag,nsym
    2420                 :             : !arrays
    2421                 :             :  integer,intent(in) :: indsym(4,nsym,natom),symq(4,2,nsym),symrec(3,3,nsym)
    2422                 :             :  real(dp),intent(in) :: dyfrow(cplex,3,3,natom,1+(natom-1)*nondiag),qphon(3)
    2423                 :             :  real(dp),intent(out) :: sdyfro(cplex,3,3,natom,1+(natom-1)*nondiag)
    2424                 :             : 
    2425                 :             : !Local variables -------------------------
    2426                 :             : !scalars
    2427                 :             :  integer :: ia,indi,indj,isym,ja,kappa,mu,natom_nondiag,nsym_used,nu
    2428                 :             :  logical :: qeq0
    2429                 :             :  real(dp) :: arg,div,phasei,phaser
    2430                 :             : !arrays
    2431                 :        2706 :  real(dp) :: work(cplex,3,3)
    2432                 :             : ! *********************************************************************
    2433                 :             : 
    2434         [ +  + ]:        1353 :  if (nsym==1) then
    2435                 :             : 
    2436                 :             : !  Only symmetry is identity so simply copy
    2437   [ +  +  +  +  :       17883 :    sdyfro(:,:,:,:,:)=dyfrow(:,:,:,:,:)
          +  +  +  +  +  
                      + ]
    2438                 :             : 
    2439                 :             :  else
    2440                 :             : 
    2441                 :             : !  Actually carry out symmetrization
    2442   [ +  +  +  +  :       58028 :    sdyfro(:,:,:,:,:)=zero
          +  +  +  +  +  
                      + ]
    2443                 :        1002 :    qeq0=(qphon(1)**2+qphon(2)**2+qphon(3)**2<1.d-14)
    2444                 :             : !  === Diagonal dyn. matrix OR q=0
    2445   [ +  +  +  + ]:        1002 :    if (nondiag==0.or.qeq0) then
    2446         [ +  + ]:         988 :      natom_nondiag=1;if (nondiag==1) natom_nondiag=natom
    2447         [ +  + ]:        2054 :      do ja=1,natom_nondiag
    2448         [ +  + ]:        4526 :        do ia=1,natom
    2449         [ +  + ]:       60200 :          do isym=1,nsym
    2450                 :       56662 :            indi=indsym(4,isym,ia)
    2451         [ +  + ]:       56662 :            indj=1;if (nondiag==1) indj=indsym(4,isym,ja)
    2452   [ +  +  +  +  :     1246564 :            work(:,:,:)=zero
                   +  + ]
    2453         [ +  + ]:      226648 :            do mu=1,3
    2454         [ +  + ]:      736606 :              do nu=1,3
    2455         [ +  + ]:     2209818 :                do kappa=1,3
    2456         [ +  + ]:     3569706 :                  work(:,mu,kappa)=work(:,mu,kappa)+symrec(mu,nu,isym)*dyfrow(:,nu,kappa,indi,indj)
    2457                 :             :                end do
    2458                 :             :              end do
    2459                 :             :            end do
    2460         [ +  + ]:      229120 :            do mu=1,3
    2461         [ +  + ]:      736606 :              do nu=1,3
    2462         [ +  + ]:     2209818 :                do kappa=1,3
    2463         [ +  + ]:     3569706 :                  sdyfro(:,kappa,mu,ia,ja)=sdyfro(:,kappa,mu,ia,ja)+symrec(mu,nu,isym)*work(:,kappa,nu)
    2464                 :             :                end do
    2465                 :             :              end do
    2466                 :             :            end do
    2467                 :             :          end do
    2468                 :             :        end do
    2469                 :             :      end do
    2470                 :         988 :      div=one/dble(nsym)
    2471   [ +  +  +  +  :       56438 :      sdyfro(:,:,:,:,:)=div*sdyfro(:,:,:,:,:)
          +  +  +  +  +  
                      + ]
    2472                 :             : !    === Non diagonal dyn. matrix AND q<>0
    2473                 :             :    else
    2474         [ +  + ]:          40 :      do ja=1,natom
    2475         [ +  + ]:          90 :        do ia=1,natom
    2476                 :             :          nsym_used=0
    2477         [ +  + ]:        1298 :          do isym=1,nsym
    2478         [ +  + ]:        1298 :            if (symq(4,1,isym)==1) then
    2479                 :             :              arg=two_pi*(qphon(1)*(indsym(1,isym,ia)-indsym(1,isym,ja)) &
    2480                 :             : &             +qphon(2)*(indsym(2,isym,ia)-indsym(2,isym,ja)) &
    2481                 :         256 : &             +qphon(3)*(indsym(3,isym,ia)-indsym(3,isym,ja)))
    2482                 :         256 :              phaser=cos(arg);phasei=sin(arg)
    2483                 :         256 :              nsym_used=nsym_used+1
    2484                 :         256 :              indi=indsym(4,isym,ia)
    2485                 :         256 :              indj=indsym(4,isym,ja)
    2486   [ +  +  +  +  :        7936 :              work(:,:,:)=zero
                   +  + ]
    2487         [ +  + ]:        1024 :              do mu=1,3
    2488         [ +  + ]:        3328 :                do nu=1,3
    2489         [ +  + ]:        9984 :                  do kappa=1,3
    2490         [ +  + ]:       23040 :                    work(:,mu,kappa)=work(:,mu,kappa)+symrec(mu,nu,isym)*dyfrow(:,nu,kappa,indi,indj)
    2491                 :             :                  end do
    2492                 :             :                end do
    2493                 :             :              end do
    2494         [ +  + ]:        1024 :              do mu=1,3
    2495         [ +  + ]:        3328 :                do nu=1,3
    2496         [ +  + ]:        9984 :                  do kappa=1,3
    2497                 :             :                    sdyfro(1,kappa,mu,ia,ja)=sdyfro(1,kappa,mu,ia,ja) &
    2498                 :        9216 : &                   +symrec(mu,nu,isym)*(work(1,kappa,nu)*phaser-work(2,kappa,nu)*phasei)
    2499                 :             :                  end do
    2500                 :             :                end do
    2501                 :             :              end do
    2502         [ +  - ]:         256 :              if (cplex==2) then
    2503         [ +  + ]:        1024 :                do mu=1,3
    2504         [ +  + ]:        3328 :                  do nu=1,3
    2505         [ +  + ]:        9984 :                    do kappa=1,3
    2506                 :             :                      sdyfro(2,kappa,mu,ia,ja)=sdyfro(2,kappa,mu,ia,ja) &
    2507                 :        9216 : &                     +symrec(mu,nu,isym)*(work(1,kappa,nu)*phasei+work(2,kappa,nu)*phaser)
    2508                 :             :                    end do
    2509                 :             :                  end do
    2510                 :             :                end do
    2511                 :             :              end if
    2512                 :             :            end if
    2513                 :             :          end do
    2514                 :          50 :          div=one/dble(nsym_used)
    2515   [ +  +  +  +  :        1576 :          sdyfro(:,:,:,ia,ja)=div*sdyfro(:,:,:,ia,ja)
                   +  + ]
    2516                 :             :        end do
    2517                 :             :      end do
    2518                 :             :    end if
    2519                 :             : 
    2520                 :             :  end if
    2521                 :             : 
    2522                 :        1353 : end subroutine dfpt_sydy
    2523                 :             : !!***
    2524                 :             : 
    2525                 :             : !    CODE TO BE EVENTUALLY REUSED
    2526                 :             : !    Sym preserves direction and atom
    2527                 :             : !    if (symq(1,1,isym)==0.and.symq(2,1,isym)==0.and.symq(3,1,isym)==0.and.symq(4,1,isym)==1)then
    2528                 :             : !      if (ipert==indsym(4,isym,ipert)) then
    2529                 :             : !        tok=1
    2530                 :             : !        do idir1=1,3
    2531                 :             : !          if ((idir1==idir.and.symrec(idir,idir1,isym)/=1).or.&
    2532                 :             : ! &            (idir1/=idir.and.symrec(idir,idir1,isym)/=0)) tok=0
    2533                 :             : !        end do
    2534                 :             : !      end if
    2535                 :             : !    end if
    2536                 :             : !    div=one/dble(count(symq(4,1,:)==1))
    2537                 :             : 
    2538                 :             : !----------------------------------------------------------------------
    2539                 :             : 
    2540                 :             : !!****f* m_dynmat/wings3
    2541                 :             : !! NAME
    2542                 :             : !! wings3
    2543                 :             : !!
    2544                 :             : !! FUNCTION
    2545                 :             : !!  Suppress the wings of the cartesian 2DTE for which
    2546                 :             : !!  the diagonal element is not known
    2547                 :             : !!
    2548                 :             : !! INPUTS
    2549                 :             : !!  carflg(3,mpert,3,mpert)= ( 1 if the element of the cartesian
    2550                 :             : !!  2DTE matrix has been calculated correctly ; 0 otherwise )
    2551                 :             : !!  d2cart(2,3,mpert,3,mpert)=
    2552                 :             : !!   dynamical matrix, effective charges, dielectric tensor,....
    2553                 :             : !!   all in cartesian coordinates
    2554                 :             : !!  mpert =maximum number of ipert
    2555                 :             : !!
    2556                 :             : !! OUTPUT
    2557                 :             : !!  d2cart(2,3,mpert,3,mpert) without the wings
    2558                 :             : !!
    2559                 :             : !! SOURCE
    2560                 :             : 
    2561                 :         383 : subroutine wings3(carflg,d2cart,mpert)
    2562                 :             : 
    2563                 :             : !Arguments -------------------------------
    2564                 :             : !scalars
    2565                 :             :  integer,intent(in) :: mpert
    2566                 :             : !arrays
    2567                 :             :  integer,intent(inout) :: carflg(3,mpert,3,mpert)
    2568                 :             :  real(dp),intent(inout) :: d2cart(2,3,mpert,3,mpert)
    2569                 :             : 
    2570                 :             : !Local variables -------------------------
    2571                 :             : !scalars
    2572                 :             :  integer :: idir,idir1,ipert,ipert1
    2573                 :             : ! *********************************************************************
    2574                 :             : 
    2575         [ +  + ]:        3861 :  do ipert=1,mpert
    2576         [ +  + ]:       14295 :    do idir=1,3
    2577         [ +  + ]:       13912 :      if(carflg(idir,ipert,idir,ipert)==0)then
    2578         [ +  + ]:       86040 :        do ipert1=1,mpert
    2579         [ +  + ]:      319389 :          do idir1=1,3
    2580                 :      233349 :            carflg(idir,ipert,idir1,ipert1)=0
    2581                 :      233349 :            carflg(idir1,ipert1,idir,ipert)=0
    2582                 :      233349 :            d2cart(1,idir,ipert,idir1,ipert1)=zero
    2583                 :      233349 :            d2cart(2,idir,ipert,idir1,ipert1)=zero
    2584                 :      233349 :            d2cart(1,idir1,ipert1,idir,ipert)=zero
    2585                 :      311132 :            d2cart(2,idir1,ipert1,idir,ipert)=zero
    2586                 :             :          end do
    2587                 :             :        end do
    2588                 :             :      end if
    2589                 :             :    end do
    2590                 :             :  end do
    2591                 :             : 
    2592                 :         383 : end subroutine wings3
    2593                 :             : !!***
    2594                 :             : 
    2595                 :             : !----------------------------------------------------------------------
    2596                 :             : 
    2597                 :             : !!****f* m_dynmat/asrif9
    2598                 :             : !!
    2599                 :             : !! NAME
    2600                 :             : !! asrif9
    2601                 :             : !!
    2602                 :             : !! FUNCTION
    2603                 :             : !! Imposes the Acoustic Sum Rule to Interatomic Forces
    2604                 :             : !!
    2605                 :             : !! INPUTS
    2606                 :             : !! asr= Option for the imposition of the ASR
    2607                 :             : !!  0 => no ASR,
    2608                 :             : !!  1 => modify "asymmetrically" the diagonal element
    2609                 :             : !!  2 => modify "symmetrically" the diagonal element
    2610                 :             : !! natom= Number of atoms in the unit cell
    2611                 :             : !! nrpt= Number of R points in the Big Box
    2612                 :             : !! rpt(3,nprt)= Canonical coordinates of the R points in the unit cell
    2613                 :             : !!  These coordinates are normalized (=> * acell(3)!!)
    2614                 :             : !! wghatm(natom,natom,nrpt)= Weight associated to the couple of atoms and the R vector
    2615                 :             : !! atmfrc(3,natom,3,natom,nrpt)= Interatomic Forces
    2616                 :             : !!
    2617                 :             : !! OUTPUT
    2618                 :             : !! atmfrc(3,natom,3,natom,nrpt)= ASR-imposed Interatomic Forces
    2619                 :             : !!
    2620                 :             : !! TODO
    2621                 :             : !! List of ouput should be included.
    2622                 :             : !!
    2623                 :             : !! SOURCE
    2624                 :             : 
    2625                 :         312 : subroutine asrif9(asr,atmfrc,natom,nrpt,rpt,wghatm)
    2626                 :             : 
    2627                 :             : !Arguments -------------------------------
    2628                 :             : !scalars
    2629                 :             :  integer,intent(in) :: asr,natom,nrpt
    2630                 :             : !arrays
    2631                 :             :  real(dp),intent(in) :: rpt(3,nrpt),wghatm(natom,natom,nrpt)
    2632                 :             :  real(dp),intent(inout) :: atmfrc(3,natom,3,natom,nrpt)
    2633                 :             : 
    2634                 :             : !Local variables -------------------------
    2635                 :             : !scalars
    2636                 :             :  integer :: found,ia,ib,irpt,izero,mu,nu
    2637                 :             :  real(dp) :: sumifc
    2638                 :             : ! *********************************************************************
    2639                 :             : 
    2640         [ +  + ]:         312 :  if(asr==1.or.asr==2)then
    2641                 :             :    found=0
    2642                 :             :    ! Search for the R vector which is equal to ( 0 , 0 , 0 )
    2643                 :             :    ! This vector leaves the atom a on itself !
    2644         [ +  - ]:      293717 :    do irpt=1,nrpt
    2645   [ +  +  +  +  :      314090 :      if (all(abs(rpt(:,irpt))<=1.0d-10)) then
                   +  + ]
    2646                 :             :        found=1
    2647                 :             :        izero=irpt
    2648                 :             :      end if
    2649                 :           0 :      if (found==1) exit
    2650                 :             :    end do
    2651                 :             : 
    2652         [ -  + ]:         311 :    if(found==0)then
    2653                 :           0 :      ABI_BUG('Not able to find the vector R=(0,0,0).')
    2654                 :             :    end if
    2655                 :             : 
    2656         [ +  + ]:        1244 :    do mu=1,3
    2657         [ +  + ]:        4043 :      do nu=1,3
    2658         [ +  + ]:       11292 :        do ia=1,natom
    2659                 :             :          sumifc=zero
    2660         [ +  + ]:       41454 :          do ib=1,natom
    2661                 :             : 
    2662                 :             :            ! Get the sumifc of interatomic forces acting on the atom ia,
    2663                 :             :            ! either in a symmetrical manner, or an unsymmetrical one.
    2664         [ +  + ]:       41454 :            if(asr==1)then
    2665         [ +  + ]:    53660259 :              do irpt=1,nrpt
    2666                 :    53660259 :                sumifc=sumifc+wghatm(ia,ib,irpt)*atmfrc(mu,ia,nu,ib,irpt)
    2667                 :             :              end do
    2668                 :             :            else if(asr==2)then
    2669         [ +  + ]:    31825188 :              do irpt=1,nrpt
    2670                 :             :                sumifc=sumifc+&
    2671                 :             :                 (wghatm(ia,ib,irpt)*atmfrc(mu,ia,nu,ib,irpt)+&
    2672                 :    31825188 :                  wghatm(ia,ib,irpt)*atmfrc(nu,ia,mu,ib,irpt))/2
    2673                 :             :              end do
    2674                 :             :            end if
    2675                 :             :          end do
    2676                 :             : 
    2677                 :             :          ! Correct the self-interaction in order to fulfill the ASR
    2678                 :        7560 :          atmfrc(mu,ia,nu,ia,izero)=atmfrc(mu,ia,nu,ia,izero)-sumifc
    2679         [ +  + ]:       10359 :          if (asr==2) atmfrc(nu,ia,mu,ia,izero)=atmfrc(mu,ia,nu,ia,izero)
    2680                 :             :        end do
    2681                 :             :      end do
    2682                 :             :    end do
    2683                 :             :  end if
    2684                 :             : 
    2685                 :         312 : end subroutine asrif9
    2686                 :             : !!***
    2687                 :             : 
    2688                 :             : !----------------------------------------------------------------------
    2689                 :             : 
    2690                 :             : !!****f* m_dynmat/get_bigbox_and_weights
    2691                 :             : !! NAME
    2692                 :             : !! get_bigbox_and_weights
    2693                 :             : !!
    2694                 :             : !! FUNCTION
    2695                 :             : !! Compute the Big Box containing the R points in the cartesian real space needed to Fourier Transform
    2696                 :             : !! the dynamical matrix into its corresponding interatomic force.
    2697                 :             : !!
    2698                 :             : !! INPUTS
    2699                 :             : !! brav= Bravais Lattice (1 or -1=S.C.;2=F.C.C.;3=BCC;4=Hex.)
    2700                 :             : !! natom= Number of atoms
    2701                 :             : !! nqbz= Number of q-points in BZ.
    2702                 :             : !! ngqpt(3)= Numbers used to generate the q points to sample the Brillouin zone using an homogeneous grid
    2703                 :             : !! nqshift= number of shifts in q-mesh
    2704                 :             : !! qshift(3, nqshift) = Q-mesh shifts
    2705                 :             : !! rprim(3,3)= Normalized coordinates in real space.
    2706                 :             : !! rprimd, gprimd
    2707                 :             : !! rcan(3,natom)  = Atomic position in canonical coordinates
    2708                 :             : !! cutmode=Define the cutoff used to filter the output R-points according to their weights.
    2709                 :             : !!   0 --> No cutoff (mainly for debugging)
    2710                 :             : !!   1 --> Include only those R-points for which sum(abs(wg(:,:,irpt)) < tol20
    2711                 :             : !!         This is the approach used for the dynamical matrix.
    2712                 :             : !!   2 --> Include only those R-points for which the trace over iatom of abs(wg(iat,iat,irpt)) < tol20
    2713                 :             : !!         This option is used for objects that depend on a single atomic index.
    2714                 :             : !! comm= MPI communicator
    2715                 :             : !!
    2716                 :             : !! OUTPUT
    2717                 :             : !! nrpt= Total Number of R points in the Big Box
    2718                 :             : !! cell(3,nrpt) Give the index of the the cell and irpt
    2719                 :             : !! rpt(3,nrpt)= Canonical coordinates of the R points in the unit cell. These coordinates are normalized (=> * acell(3)!!)
    2720                 :             : !! r_inscribed_sphere
    2721                 :             : !! wghatm(natom,natom,nrpt)= Weights associated to a pair of atoms and to a R vector
    2722                 :             : !!
    2723                 :             : !! SOURCE
    2724                 :             : 
    2725                 :           0 : subroutine get_bigbox_and_weights(brav, natom, nqbz, ngqpt, nqshift, qshift, rprim, rprimd, gprim, rcan, &
    2726                 :             :                                   cutmode, nrpt, rpt, cell, wghatm, r_inscribed_sphere, comm)
    2727                 :             : 
    2728                 :             : !Arguments -------------------------------
    2729                 :             : !scalars
    2730                 :             :  integer,intent(in) :: brav, natom, nqbz, nqshift, cutmode, comm
    2731                 :             :  integer,intent(out) :: nrpt
    2732                 :             :  real(dp),intent(out) :: r_inscribed_sphere
    2733                 :             : !arrays
    2734                 :             :  integer,intent(in) :: ngqpt(3)
    2735                 :             :  real(dp),intent(in) :: gprim(3,3),rprim(3,3),rprimd(3,3), rcan(3, natom)
    2736                 :             :  real(dp),intent(in) :: qshift(3, nqshift)
    2737                 :             :  integer,allocatable,intent(out) :: cell(:,:)
    2738                 :             :  real(dp),allocatable,intent(out) :: rpt(:,:), wghatm(:,:,:)
    2739                 :             : 
    2740                 :             : !Local variables -------------------------
    2741                 :             : !scalars
    2742                 :             :  integer :: my_ierr, ierr, ii, irpt, all_nrpt
    2743                 :             :  real(dp) :: toldist
    2744                 :             :  integer :: ngqpt9(9)
    2745                 :             :  character(len=500*4) :: msg
    2746                 :             : !arrays
    2747                 :           0 :  integer,allocatable :: all_cell(:,:)
    2748                 :           0 :  real(dp),allocatable :: all_rpt(:,:), all_wghatm(:,:,:)
    2749                 :             : ! *********************************************************************
    2750                 :             : 
    2751   [ #  #  #  #  :           0 :  ABI_CHECK(any(cutmode == [0, 1, 2]), "cutmode should be in [0, 1, 2]")
                   #  # ]
    2752                 :             : 
    2753                 :             :  ! Create the Big Box of R vectors in real space and compute the number of points (cells) in real space
    2754                 :           0 :  call make_bigbox(brav, all_cell, ngqpt, nqshift, rprim, all_nrpt, all_rpt)
    2755                 :             : 
    2756                 :             :  ! Weights associated to these R points and to atomic pairs
    2757   [ #  #  #  #  :           0 :  ABI_MALLOC(all_wghatm, (natom, natom, all_nrpt))
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    2758                 :             : 
    2759                 :             :  ! HM: this tolerance is highly dependent on the compilation/architecture
    2760                 :             :  !     numeric errors in the DDB text file. Try a few tolerances and check whether all the weights are found.
    2761         [ #  # ]:           0 :  ngqpt9 = 0; ngqpt9(1:3) = ngqpt(1:3)
    2762                 :           0 :  toldist = tol8
    2763         [ #  # ]:           0 :  do while (toldist <= tol6)
    2764                 :             :    ! Note ngqpt(9) with intent(inout)!
    2765                 :             :    call wght9(brav, gprim, natom, ngqpt9, nqbz, nqshift, all_nrpt, qshift, rcan, &
    2766                 :           0 :               all_rpt, rprimd, toldist, r_inscribed_sphere, all_wghatm, my_ierr)
    2767                 :           0 :    call xmpi_max(my_ierr, ierr, comm, ii)
    2768         [ #  # ]:           0 :    if (ierr > 0) toldist = toldist * 10
    2769         [ #  # ]:           0 :    if (ierr == 0) exit
    2770                 :             :  end do
    2771                 :             : 
    2772         [ #  # ]:           0 :  if (ierr > 0) then
    2773                 :             :    write(msg, '(3a,es14.4,2a,i0, 14a)' ) &
    2774                 :           0 :     'The sum of the weight is not equal to nqpt.',ch10,&
    2775   [ #  #  #  #  :           0 :     'The sum of the weights is: ',sum(all_wghatm),ch10,&
                   #  # ]
    2776                 :           0 :     'The number of q points is: ',nqbz, ch10, &
    2777                 :           0 :     'This might have several sources.',ch10,&
    2778                 :           0 :     'If toldist is larger than 1.0e-8, the atom positions might be loose.',ch10,&
    2779                 :           0 :     'and the q point weights not computed properly.',ch10,&
    2780                 :           0 :     'Action: make input atomic positions more symmetric.',ch10,&
    2781                 :           0 :     'Otherwise, you might increase "buffer" in m_dynmat.F90 see bigbx9 subroutine and recompile.',ch10,&
    2782                 :           0 :     'Actually, this can also happen when ngqpt is 0 0 0,',ch10,&
    2783                 :           0 :     'if abs(brav) /= 1, in this case you should change brav to 1. If brav is already set to 1 (default) try -1.'
    2784                 :           0 :    ABI_ERROR(msg)
    2785                 :             :  end if
    2786                 :             : 
    2787                 :             :  ! Only conserve the necessary points in rpt.
    2788                 :           0 :  nrpt = 0
    2789         [ #  # ]:           0 :  do irpt=1,all_nrpt
    2790         [ #  # ]:           0 :    if (filterw(all_wghatm(:,:,irpt))) cycle
    2791                 :           0 :    nrpt = nrpt + 1
    2792                 :             :  end do
    2793                 :             : 
    2794                 :             :  ! Allocate output arrays and transfer data.
    2795   [ #  #  #  #  :           0 :  ABI_MALLOC(rpt, (3, nrpt))
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    2796   [ #  #  #  #  :           0 :  ABI_MALLOC(cell, (3, nrpt))
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    2797   [ #  #  #  #  :           0 :  ABI_MALLOC(wghatm, (natom, natom, nrpt))
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    2798                 :             : 
    2799                 :           0 :  ii = 0
    2800         [ #  # ]:           0 :  do irpt=1,all_nrpt
    2801         [ #  # ]:           0 :    if (filterw(all_wghatm(:,:,irpt))) cycle
    2802                 :           0 :    ii = ii + 1
    2803         [ #  # ]:           0 :    rpt(:, ii) = all_rpt(:,irpt)
    2804   [ #  #  #  # ]:           0 :    wghatm(:,:,ii) = all_wghatm(:,:,irpt)
    2805         [ #  # ]:           0 :    cell(:,ii) = all_cell(:,irpt)
    2806                 :             :  end do
    2807                 :             : 
    2808         [ #  # ]:           0 :  ABI_FREE(all_rpt)
    2809         [ #  # ]:           0 :  ABI_FREE(all_wghatm)
    2810         [ #  # ]:           0 :  ABI_FREE(all_cell)
    2811                 :             : 
    2812                 :             : contains
    2813                 :             : 
    2814                 :           0 : logical pure function filterw(wg)
    2815                 :             : 
    2816                 :             :  real(dp),intent(in) :: wg(natom,natom)
    2817                 :             :  integer :: iat
    2818                 :             :  real(dp) :: trace
    2819                 :             : 
    2820                 :           0 :  select case (cutmode)
    2821                 :             :  case (1)
    2822   [ #  #  #  # ]:           0 :    filterw = sum(abs(wg)) < tol20
    2823                 :             :  case (2)
    2824                 :             :    trace = zero
    2825         [ #  # ]:           0 :    do iat=1,natom
    2826                 :           0 :      trace = trace + abs(wg(iat,iat))
    2827                 :             :    end do
    2828                 :           0 :    filterw = trace < tol20
    2829                 :             :  case default
    2830      [ #  #  # ]:           0 :    filterw = .False.
    2831                 :             :  end select
    2832                 :             : 
    2833                 :           0 : end function filterw
    2834                 :             : 
    2835                 :             : end subroutine get_bigbox_and_weights
    2836                 :             : !!***
    2837                 :             : 
    2838                 :             : !----------------------------------------------------------------------
    2839                 :             : 
    2840                 :             : !!****f* m_dynmat/make_bigbox
    2841                 :             : !! NAME
    2842                 :             : !! make_bigbox
    2843                 :             : !!
    2844                 :             : !! FUNCTION
    2845                 :             : !! Helper functions to faciliate the generation of a Big Box containing
    2846                 :             : !! all the R points in the cartesian real space needed to Fourier Transform
    2847                 :             : !! the dynamical matrix into its corresponding interatomic force.
    2848                 :             : !! See bigbx9 for the algorithm.
    2849                 :             : !!
    2850                 :             : !! INPUTS
    2851                 :             : !! brav= Bravais Lattice (1 or -1=S.C.;2=F.C.C.;3=BCC;4=Hex.)
    2852                 :             : !! ngqpt(3)= Numbers used to generate the q points to sample the
    2853                 :             : !!   Brillouin zone using an homogeneous grid
    2854                 :             : !! nqshft= number of q-points in the repeated cell for the Brillouin zone sampling
    2855                 :             : !!  When nqshft is not 1, but 2 or 4 (only other allowed values),
    2856                 :             : !!  the limits for the big box have to be extended by a factor of 2.
    2857                 :             : !! rprim(3,3)= Normalized coordinates in real space  !!! IS THIS CORRECT?
    2858                 :             : !!
    2859                 :             : !! OUTPUT
    2860                 :             : !! cell(3,nrpt)= integer coordinates of the cells (R points) in the rprim basis
    2861                 :             : !! nprt= Number of cells (R points) in the Big Box
    2862                 :             : !! rpt(3,mrpt)= canonical coordinates of the cells (R points)
    2863                 :             : !!  These coordinates are normalized (=> * acell(3)!!)
    2864                 :             : !!  The array is allocated here with the proper dimension. Client code is responsible
    2865                 :             : !!  for the deallocation.
    2866                 :             : !!
    2867                 :             : !! SOURCE
    2868                 :             : 
    2869                 :         244 : subroutine make_bigbox(brav, cell, ngqpt, nqshft, rprim, nrpt, rpt)
    2870                 :             : 
    2871                 :             : !Arguments -------------------------------
    2872                 :             : !scalars
    2873                 :             :  integer,intent(in) :: brav,nqshft
    2874                 :             :  integer,intent(out) :: nrpt
    2875                 :             : !arrays
    2876                 :             :  integer,intent(in) :: ngqpt(3)
    2877                 :             :  real(dp),intent(in) :: rprim(3,3)
    2878                 :             :  real(dp),allocatable,intent(out) :: rpt(:,:)
    2879                 :             :  integer,allocatable,intent(out) :: cell(:,:)
    2880                 :             : 
    2881                 :             : !Local variables -------------------------
    2882                 :             : !scalars
    2883                 :             :  integer :: choice,mrpt
    2884                 :             : !arrays
    2885                 :             :  real(dp) :: dummy_rpt(3,1)
    2886                 :             :  integer:: dummy_cell(1,3)
    2887                 :             : ! *********************************************************************
    2888                 :             : 
    2889                 :             :  ! Compute the number of points (cells) in real space
    2890                 :         244 :  choice=0
    2891                 :         244 :  call bigbx9(brav,dummy_cell,choice,1,ngqpt,nqshft,mrpt,rprim,dummy_rpt)
    2892                 :             : 
    2893                 :             :  ! Now we can allocate and calculate the points and the weights.
    2894                 :         244 :  nrpt = mrpt
    2895   [ -  +  +  -  :         732 :  ABI_MALLOC(rpt,(3,nrpt))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
    2896   [ -  +  +  -  :         732 :  ABI_MALLOC(cell,(3,nrpt))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
    2897                 :             : 
    2898                 :         244 :  choice=1
    2899                 :         244 :  call bigbx9(brav,cell,choice,mrpt,ngqpt,nqshft,nrpt,rprim,rpt)
    2900                 :             : 
    2901                 :         244 : end subroutine make_bigbox
    2902                 :             : !!***
    2903                 :             : 
    2904                 :             : !----------------------------------------------------------------------
    2905                 :             : 
    2906                 :             : !!****f* m_dynmat/bigbx9
    2907                 :             : !! NAME
    2908                 :             : !! bigbx9
    2909                 :             : !!
    2910                 :             : !! FUNCTION
    2911                 :             : !! Generation of a Big Box containing all the R points (cells) in the
    2912                 :             : !! cartesian real space needed to Fourier Transforms the dynamical
    2913                 :             : !! matrix into its corresponding interatomic force.
    2914                 :             : !!
    2915                 :             : !! INPUTS
    2916                 :             : !! brav= Bravais Lattice (1 or -1=S.C.;2=F.C.C.;3=BCC;4=Hex.)
    2917                 :             : !! choice= if 0, simply count nrpt ; if 1, checks that the input mrpt
    2918                 :             : !!   is the same as nrpt, and generate rpt(3,mrpt)
    2919                 :             : !! mrpt=dimension of rpt
    2920                 :             : !! ngqpt(3)= Numbers used to generate the q points to sample the
    2921                 :             : !!  Brillouin zone using an homogeneous grid
    2922                 :             : !! nqshft= number of q-points in the repeated cell for the Brillouin zone sampling
    2923                 :             : !!  When nqshft is not 1, but 2 or 4 (only other allowed values),
    2924                 :             : !!  the limits for the big box have to be extended by a factor of 2.
    2925                 :             : !! rprim(3,3)= Normalized coordinates in real space  !!! IS THIS CORRECT?
    2926                 :             : !!
    2927                 :             : !! OUTPUT
    2928                 :             : !! cell(3,nrpt)= integer coordinates of the cells (R points) in the rprim basis
    2929                 :             : !! nprt= Number of cells (R points) in the Big Box
    2930                 :             : !! rpt(3,mrpt)= canonical coordinates of the cells (R points)
    2931                 :             : !!  These coordinates are normalized (=> * acell(3)!!)
    2932                 :             : !!  (output only if choice=1)
    2933                 :             : !!
    2934                 :             : !! SOURCE
    2935                 :             : 
    2936                 :         488 : subroutine bigbx9(brav,cell,choice,mrpt,ngqpt,nqshft,nrpt,rprim,rpt)
    2937                 :             : 
    2938                 :             : !Arguments -------------------------------
    2939                 :             : !scalars
    2940                 :             :  integer,intent(in) :: brav,choice,mrpt,nqshft
    2941                 :             :  integer,intent(out) :: nrpt
    2942                 :             : !arrays
    2943                 :             :  integer,intent(in) :: ngqpt(3)
    2944                 :             :  real(dp),intent(in) :: rprim(3,3)
    2945                 :             :  real(dp),intent(out) :: rpt(3,mrpt)
    2946                 :             :  integer,intent(out) :: cell(3,mrpt)
    2947                 :             : 
    2948                 :             : !Local variables -------------------------
    2949                 :             : !In some cases, the atoms coordinates are not packed in the
    2950                 :             : ! [0,1]^3 cube. Then, the parameter "buffer" might be increased,
    2951                 :             : !to search relevant pairs of atoms in bigger boxes than usual.
    2952                 :             : !scalars
    2953                 :             :  integer,parameter :: buffer=1
    2954                 :             :  integer :: irpt,lim1,lim2,lim3,lqshft,r1,r2,r3
    2955                 :             :  character(len=500) :: msg
    2956                 :             : ! *********************************************************************
    2957                 :             : 
    2958                 :         488 :  lqshft=1
    2959         [ +  + ]:         488 :  if(nqshft/=1)lqshft=2
    2960                 :             : 
    2961                 :             : 
    2962                 :             : !Simple Cubic Lattice
    2963         [ +  + ]:         488 :  if (abs(brav)==1) then
    2964                 :         398 :    lim1=((ngqpt(1))+1)*lqshft+buffer
    2965                 :         398 :    lim2=((ngqpt(2))+1)*lqshft+buffer
    2966                 :         398 :    lim3=((ngqpt(3))+1)*lqshft+buffer
    2967                 :         398 :    nrpt=(2*lim1+1)*(2*lim2+1)*(2*lim3+1)
    2968         [ +  + ]:         398 :    if(choice/=0)then
    2969         [ -  + ]:         199 :      if (nrpt/=mrpt) then
    2970                 :           0 :        write(msg,'(2(a,i0))')' nrpt=',nrpt,' is not equal to mrpt= ',mrpt
    2971                 :           0 :        ABI_BUG(msg)
    2972                 :             :      end if
    2973                 :         199 :      irpt=0
    2974         [ +  + ]:        2612 :      do r1=-lim1,lim1
    2975         [ +  + ]:       37035 :        do r2=-lim2,lim2
    2976         [ +  + ]:      528549 :          do r3=-lim3,lim3
    2977                 :      491713 :            irpt=irpt+1
    2978                 :      491713 :            rpt(1,irpt)=r1*rprim(1,1)+r2*rprim(1,2)+r3*rprim(1,3)
    2979                 :      491713 :            rpt(2,irpt)=r1*rprim(2,1)+r2*rprim(2,2)+r3*rprim(2,3)
    2980                 :      491713 :            rpt(3,irpt)=r1*rprim(3,1)+r2*rprim(3,2)+r3*rprim(3,3)
    2981                 :      526136 :            cell(1,irpt)=r1;cell(2,irpt)=r2;cell(3,irpt)=r3
    2982                 :             :          end do
    2983                 :             :        end do
    2984                 :             :      end do
    2985                 :             :    end if
    2986                 :             : 
    2987                 :             : !  Face Centered Cubic Lattice
    2988         [ +  + ]:          90 :  else if (brav==2) then
    2989                 :          60 :    lim1=((ngqpt(1)+3)/4)*lqshft+buffer
    2990                 :          60 :    lim2=((ngqpt(2)+3)/4)*lqshft+buffer
    2991                 :          60 :    lim3=((ngqpt(3)+3)/4)*lqshft+buffer
    2992                 :          60 :    nrpt=(2*lim1+1)*(2*lim2+1)*(2*lim3+1)*4
    2993         [ +  + ]:          60 :    if(choice/=0)then
    2994         [ -  + ]:          30 :      if (nrpt/=mrpt) then
    2995                 :           0 :        write(msg,'(2(a,i0))')' nrpt=',nrpt,' is not equal to mrpt= ',mrpt
    2996                 :           0 :        ABI_BUG(msg)
    2997                 :             :      end if
    2998                 :          30 :      irpt=0
    2999         [ +  + ]:         228 :      do r1=-lim1,lim1
    3000         [ +  + ]:        1554 :        do r2=-lim2,lim2
    3001         [ +  + ]:       10506 :          do r3=-lim3,lim3
    3002                 :        8982 :            irpt=irpt+4
    3003                 :        8982 :            rpt(1,irpt-3)=r1
    3004                 :        8982 :            rpt(2,irpt-3)=r2
    3005                 :        8982 :            rpt(3,irpt-3)=r3
    3006                 :        8982 :            rpt(1,irpt-2)=r1
    3007                 :        8982 :            rpt(2,irpt-2)=r2+0.5
    3008                 :        8982 :            rpt(3,irpt-2)=r3+0.5
    3009                 :        8982 :            rpt(1,irpt-1)=r1+0.5
    3010                 :        8982 :            rpt(2,irpt-1)=r2
    3011                 :        8982 :            rpt(3,irpt-1)=r3+0.5
    3012                 :        8982 :            rpt(1,irpt)=r1+0.5
    3013                 :        8982 :            rpt(2,irpt)=r2+0.5
    3014                 :        8982 :            rpt(3,irpt)=r3
    3015                 :             : !TEST_AM
    3016                 :             : !           cell(irpt-3,1)=r1;cell(irpt-3,2)=r2;cell(irpt-3,3)=r3
    3017                 :       10308 :            cell(1,irpt)=r1;cell(2,irpt)=r2;cell(3,irpt)=r3
    3018                 :             :          end do
    3019                 :             :        end do
    3020                 :             :      end do
    3021                 :             :    end if
    3022                 :             : 
    3023                 :             : !  Body Centered Cubic Lattice
    3024         [ +  + ]:          30 :  else if (brav==3) then
    3025                 :          14 :    lim1=((ngqpt(1)+3)/4)*lqshft+buffer
    3026                 :          14 :    lim2=((ngqpt(2)+3)/4)*lqshft+buffer
    3027                 :          14 :    lim3=((ngqpt(3)+3)/4)*lqshft+buffer
    3028                 :          14 :    nrpt=(2*lim1+1)*(2*lim2+1)*(2*lim3+1)*2
    3029         [ +  + ]:          14 :    if(choice/=0)then
    3030         [ -  + ]:           7 :      if(nrpt/=mrpt) then
    3031                 :           0 :        write(msg,'(2(a,i0))')' nrpt= ',nrpt,' is not equal to mrpt= ',mrpt
    3032                 :           0 :        ABI_BUG(msg)
    3033                 :             :      end if
    3034                 :           7 :      irpt=0
    3035         [ +  + ]:          56 :      do r1=-lim1,lim1
    3036         [ +  + ]:         399 :        do r2=-lim2,lim2
    3037         [ +  + ]:        2793 :          do r3=-lim3,lim3
    3038                 :        2401 :            irpt=irpt+2
    3039                 :        2401 :            rpt(1,irpt-1)=r1
    3040                 :        2401 :            rpt(2,irpt-1)=r2
    3041                 :        2401 :            rpt(3,irpt-1)=r3
    3042                 :        2401 :            rpt(1,irpt)=r1+0.5
    3043                 :        2401 :            rpt(2,irpt)=r2+0.5
    3044                 :        2401 :            rpt(3,irpt)=r3+0.5
    3045                 :             : !TEST_AM
    3046                 :             : !           cell(irpt-1,1)=r1;cell(irpt-1,2)=r2;cell(irpt-1,3)=r3
    3047                 :        2744 :            cell(1,irpt)=r1;cell(2,irpt)=r2;cell(3,irpt)=r3
    3048                 :             :          end do
    3049                 :             :        end do
    3050                 :             :      end do
    3051                 :             :    end if
    3052                 :             : 
    3053                 :             : !  Hexagonal Lattice
    3054         [ +  - ]:          16 :  else if (brav==4) then
    3055                 :          16 :    lim1=(ngqpt(1)+1)*lqshft+buffer
    3056                 :          16 :    lim2=(ngqpt(2)+1)*lqshft+buffer
    3057                 :          16 :    lim3=((ngqpt(3)/2)+1)*lqshft+buffer
    3058                 :          16 :    nrpt=(2*lim1+1)*(2*lim2+1)*(2*lim3+1)
    3059         [ +  + ]:          16 :    if(choice/=0)then
    3060         [ -  + ]:           8 :      if(nrpt/=mrpt)then
    3061                 :           0 :        write(msg,'(2(a,i0))')' nrpt=',nrpt,' is not equal to mrpt=',mrpt
    3062                 :           0 :        ABI_BUG(msg)
    3063                 :             :      end if
    3064                 :           8 :      irpt=0
    3065         [ +  + ]:         142 :      do r1=-lim1,lim1
    3066         [ +  + ]:        2582 :        do r2=-lim2,lim2
    3067         [ +  + ]:       27356 :          do r3=-lim3,lim3
    3068                 :       24782 :            irpt=irpt+1
    3069                 :       24782 :            rpt(1,irpt)=r1*rprim(1,1)+r2*rprim(1,2)+r3*rprim(1,3)
    3070                 :       24782 :            rpt(2,irpt)=r1*rprim(2,1)+r2*rprim(2,2)+r3*rprim(2,3)
    3071                 :       24782 :            rpt(3,irpt)=r1*rprim(3,1)+r2*rprim(3,2)+r3*rprim(3,3)
    3072                 :       27222 :            cell(1,irpt)=r1;cell(2,irpt)=r2;cell(3,irpt)=r3
    3073                 :             :          end do
    3074                 :             :        end do
    3075                 :             :      end do
    3076                 :             :    end if
    3077                 :             : 
    3078                 :             :  else
    3079                 :           0 :    write(msg,'(a,i0,a)')' The value of brav= ',brav,' is not allowed (should be -1, 1, 2 or 4).'
    3080                 :           0 :    ABI_BUG(msg)
    3081                 :             :  end if
    3082                 :             : 
    3083                 :         488 : end subroutine bigbx9
    3084                 :             : !!***
    3085                 :             : 
    3086                 :             : !----------------------------------------------------------------------
    3087                 :             : 
    3088                 :             : !!****f* m_dynmat/canat9
    3089                 :             : !! NAME
    3090                 :             : !! canat9
    3091                 :             : !!
    3092                 :             : !! FUNCTION
    3093                 :             : !! Transforms an atom whose coordinates (xred*rprim) would not be
    3094                 :             : !! in the chosen unit cell used to generate the interatomic forces
    3095                 :             : !! to its correspondent (rcan) in canonical coordinates.
    3096                 :             : !!
    3097                 :             : !! INPUTS
    3098                 :             : !! brav= Bravais Lattice (1 or -1=S.C.;2=F.C.C.;3=BCC;4=Hex.)
    3099                 :             : !! natom= Number of atoms in the unit cell
    3100                 :             : !! rprim(3,3)= Normalized coordinates  of primitive vectors
    3101                 :             : !!
    3102                 :             : !! OUTPUT
    3103                 :             : !! rcan(3,natom)  = Atomic position in canonical coordinates
    3104                 :             : !! trans(3,natom) = Atomic translations : xred = rcan + trans
    3105                 :             : !!
    3106                 :             : !! SOURCE
    3107                 :             : 
    3108                 :             : 
    3109                 :         244 : subroutine canat9(brav,natom,rcan,rprim,trans,xred)
    3110                 :             : 
    3111                 :             : !Arguments -------------------------------
    3112                 :             : !scalars
    3113                 :             :  integer,intent(in) :: brav,natom
    3114                 :             : !arrays
    3115                 :             :  real(dp),intent(in) :: rprim(3,3),xred(3,natom)
    3116                 :             :  real(dp),intent(out) :: rcan(3,natom),trans(3,natom)
    3117                 :             : 
    3118                 :             : !Local variables -------------------------
    3119                 :             : !scalars
    3120                 :             :  integer :: found,iatom,ii
    3121                 :             :  character(len=500) :: msg
    3122                 :             : !arrays
    3123                 :             :  real(dp) :: dontno(3,4),rec(3),rok(3),shift(3),tt(3)
    3124                 :             : ! *********************************************************************
    3125                 :             : 
    3126                 :             : !Normalization of the cartesian atomic coordinates
    3127                 :             : !If not normalized : rcan(i) <- rcan(i) * acell(i)
    3128         [ +  + ]:         887 :  do iatom=1,natom
    3129         [ +  + ]:        2816 :    rcan(:,iatom)=xred(1,iatom)*rprim(:,1)+xred(2,iatom)*rprim(:,2)+xred(3,iatom)*rprim(:,3)
    3130                 :             :  end do
    3131                 :             : 
    3132                 :             :  !Study of the different cases for the Bravais lattice:
    3133         [ +  + ]:         244 :  if (abs(brav)==1) then
    3134                 :             :    !Simple Cubic Lattice
    3135                 :             : 
    3136         [ +  + ]:         745 :    do iatom=1,natom
    3137                 :             :      ! Canon will produces these coordinate transformations
    3138                 :             :      ! (Note: here we still use reduced coordinates )
    3139                 :         546 :      call wrap2_pmhalf(xred(1,iatom),rok(1),shift(1))
    3140                 :         546 :      call wrap2_pmhalf(xred(2,iatom),rok(2),shift(2))
    3141                 :         546 :      call wrap2_pmhalf(xred(3,iatom),rok(3),shift(3))
    3142                 :             : 
    3143                 :             : !    New coordinates : rcan
    3144         [ +  + ]:        2184 :      rcan(:,iatom)=rok(1)*rprim(:,1)+rok(2)*rprim(:,2)+rok(3)*rprim(:,3)
    3145                 :             : !    Translations between New and Old coordinates
    3146         [ +  + ]:        2184 :      tt(:)=xred(1,iatom)*rprim(:,1)+xred(2,iatom)*rprim(:,2)+xred(3,iatom)*rprim(:,3)
    3147         [ +  + ]:        2383 :      trans(:,iatom)=tt(:)-rcan(:,iatom)
    3148                 :             :    end do
    3149                 :             : 
    3150         [ +  + ]:          45 :  else if (brav==2) then
    3151                 :             :    ! Face Centered Lattice
    3152                 :             :    ! Special possible translations in the F.C.C. case
    3153                 :          30 :    dontno(:,:)=zero
    3154                 :          30 :    dontno(2,2)=0.5_dp
    3155                 :          30 :    dontno(3,2)=0.5_dp
    3156                 :          30 :    dontno(1,3)=0.5_dp
    3157                 :          30 :    dontno(3,3)=0.5_dp
    3158                 :          30 :    dontno(1,4)=0.5_dp
    3159                 :          30 :    dontno(2,4)=0.5_dp
    3160         [ +  + ]:          90 :    do iatom=1,natom
    3161                 :             :      found=0
    3162         [ +  + ]:         169 :      do ii=1,4
    3163         [ +  + ]:         135 :        if (found==1) exit
    3164                 :             :        ! Canon will produce these coordinate transformations
    3165                 :          79 :        call wrap2_pmhalf(rcan(1,iatom)+dontno(1,ii),rok(1),shift(1))
    3166                 :          79 :        call wrap2_pmhalf(rcan(2,iatom)+dontno(2,ii),rok(2),shift(2))
    3167                 :          79 :        call wrap2_pmhalf(rcan(3,iatom)+dontno(3,ii),rok(3),shift(3))
    3168                 :             :        ! In the F.C.C., ABS[ Ri ] + ABS[ Rj ] < or = 1/2
    3169                 :             :        ! The equal sign hase been treated using a tolerance parameter
    3170                 :             :        ! not to have twice the same point in the unit cell !
    3171                 :          79 :        rok(1)=rok(1)-1.0d-10
    3172                 :          79 :        rok(2)=rok(2)-2.0d-10
    3173                 :          79 :        rok(3)=rok(3)-5.0d-10
    3174         [ +  + ]:         139 :        if (abs(rok(1))+abs(rok(2))<=0.5_dp) then
    3175         [ +  - ]:          64 :          if (abs(rok(1))+abs(rok(3))<=0.5_dp) then
    3176         [ +  + ]:          64 :            if (abs(rok(2))+abs(rok(3))<=0.5_dp) then
    3177         [ +  + ]:         240 :              tt(:)=rcan(:,iatom)
    3178                 :             :              ! New coordinates : rcan
    3179                 :          60 :              rcan(1,iatom)=rok(1)+1.0d-10
    3180                 :          60 :              rcan(2,iatom)=rok(2)+2.0d-10
    3181                 :          60 :              rcan(3,iatom)=rok(3)+5.0d-10
    3182                 :             :              ! Translations between New and Old coordinates
    3183         [ +  + ]:         240 :              trans(:,iatom)=tt(:)-rcan(:,iatom)
    3184                 :             :              found=1
    3185                 :             :            end if
    3186                 :             :          end if
    3187                 :             :        end if
    3188                 :             :      end do
    3189                 :             :    end do
    3190                 :             : 
    3191         [ +  + ]:          15 :  else if (brav==3) then
    3192                 :             :    ! Body Centered Cubic Lattice
    3193                 :             :    ! Special possible translations in the B.C.C. case
    3194         [ +  + ]:          28 :    dontno(:,1)=zero
    3195         [ +  + ]:          28 :    dontno(:,2)=0.5_dp
    3196         [ +  + ]:          14 :    do iatom=1,natom
    3197                 :             :      found=0
    3198         [ +  - ]:          21 :      do ii=1,2
    3199         [ +  + ]:          14 :        if (found==1) exit
    3200                 :             :        ! Canon will produce these coordinate transformations
    3201                 :           7 :        call wrap2_pmhalf(rcan(1,iatom)+dontno(1,ii),rok(1),shift(1))
    3202                 :           7 :        call wrap2_pmhalf(rcan(2,iatom)+dontno(2,ii),rok(2),shift(2))
    3203                 :           7 :        call wrap2_pmhalf(rcan(3,iatom)+dontno(3,ii),rok(3),shift(3))
    3204                 :             :        ! In the F.C.C., ABS[ Ri ] < or = 1/2
    3205                 :             :        ! and    ABS[ R1 ] + ABS[ R2 ] + ABS[ R3 ] < or = 3/4
    3206                 :             :        ! The equal signs have been treated using a tolerance parameter
    3207                 :             :        ! not to have twice the same point in the unit cell !
    3208                 :           7 :        rok(1)=rok(1)-1.0d-10
    3209                 :           7 :        rok(2)=rok(2)-2.0d-10
    3210                 :           7 :        rok(3)=rok(3)-5.0d-10
    3211         [ +  - ]:          14 :        if(abs(rok(1))+abs(rok(2))+abs(rok(3))<=0.75_dp)then
    3212   [ +  -  +  -  :           7 :          if ( abs(rok(1))<=0.5_dp .and. abs(rok(2))<=0.5_dp .and. abs(rok(3))<=0.5_dp) then
                   +  - ]
    3213         [ +  + ]:          28 :            tt(:)=rcan(:,iatom)
    3214                 :             :            ! New coordinates : rcan
    3215                 :           7 :            rcan(1,iatom)=rok(1)+1.0d-10
    3216                 :           7 :            rcan(2,iatom)=rok(2)+2.0d-10
    3217                 :           7 :            rcan(3,iatom)=rok(3)+5.0d-10
    3218                 :             :            ! Translations between New and Old coordinates
    3219         [ +  + ]:          28 :            trans(:,iatom)=tt(:)-rcan(:,iatom)
    3220                 :             :            found=1
    3221                 :             :          end if
    3222                 :             :        end if
    3223                 :             :      end do
    3224                 :             :    end do
    3225                 :             : 
    3226         [ +  - ]:           8 :  else if (brav==4) then
    3227                 :             :    ! Hexagonal Lattice
    3228                 :             :    ! In this case, it is easier first to work in reduced coordinates space !
    3229         [ +  + ]:          38 :    do iatom=1,natom
    3230                 :             :      ! Passage from the reduced space to the "lozenge" cell
    3231                 :          30 :      rec(1)=xred(1,iatom)-0.5_dp
    3232                 :          30 :      rec(2)=xred(2,iatom)-0.5_dp
    3233                 :          30 :      rec(3)=xred(3,iatom)
    3234                 :             :      ! Canon will produces these coordinate transformations
    3235                 :          30 :      call wrap2_pmhalf(rec(1),rok(1),shift(1))
    3236                 :          30 :      call wrap2_pmhalf(rec(2),rok(2),shift(2))
    3237                 :          30 :      call wrap2_pmhalf(rec(3),rok(3),shift(3))
    3238                 :          30 :      rec(1)=rok(1)+0.5_dp
    3239                 :          30 :      rec(2)=rok(2)+0.5_dp
    3240                 :          30 :      rec(3)=rok(3)
    3241                 :             :      ! Passage in Cartesian Normalized Coordinates
    3242         [ +  + ]:         120 :      rcan(:,iatom)=rec(1)*rprim(:,1)+rec(2)*rprim(:,2)+rec(3)*rprim(:,3)
    3243                 :             :      ! Use of a tolerance parameter not to have twice the same point in the unit cell !
    3244                 :          30 :      rcan(1,iatom)=rcan(1,iatom)-1.0d-10
    3245                 :          30 :      rcan(2,iatom)=rcan(2,iatom)-2.0d-10
    3246                 :             :      ! Passage to the honeycomb hexagonal unit cell !
    3247         [ +  + ]:          30 :      if (rcan(1,iatom)>0.5_dp) then
    3248                 :           6 :        rcan(1,iatom)=rcan(1,iatom)-1.0_dp
    3249                 :             :      end if
    3250   [ +  +  +  + ]:          30 :      if (rcan(1,iatom)>zero.and.rcan(1,iatom)+sqrt(3.0_dp)*rcan(2,iatom)>1.0_dp) then
    3251                 :          10 :        rcan(1,iatom)=rcan(1,iatom)-0.5_dp
    3252                 :          10 :        rcan(2,iatom)=rcan(2,iatom)-sqrt(3.0_dp)*0.5_dp
    3253                 :             :      end if
    3254   [ +  +  +  + ]:          30 :      if (rcan(1,iatom)<=zero.and.sqrt(3.0_dp)*rcan(2,iatom)-rcan(1,iatom)>1.0_dp) then
    3255                 :           6 :        rcan(1,iatom)=rcan(1,iatom)+0.5_dp
    3256                 :           6 :        rcan(2,iatom)=rcan(2,iatom)-sqrt(3.0_dp)*0.5_dp
    3257                 :             :      end if
    3258                 :             :      ! Translations between New and Old coordinates
    3259         [ +  + ]:         120 :      tt(:)=xred(1,iatom)*rprim(:,1)+xred(2,iatom)*rprim(:,2)+xred(3,iatom)*rprim(:,3)
    3260         [ +  + ]:         128 :      trans(:,iatom)=tt(:)-rcan(:,iatom)
    3261                 :             :    end do
    3262                 :             : 
    3263                 :             :    ! End of the possible cases for brav : -1, 1, 2, 4.
    3264                 :             :  else
    3265                 :             :    write(msg, '(a,i0,a,a,a)' )&
    3266                 :           0 :    'The required value of brav=',brav,' is not available.',ch10,&
    3267                 :           0 :    'It should be -1, 1,2 or 4 .'
    3268                 :           0 :    ABI_BUG(msg)
    3269                 :             :  end if
    3270                 :             : 
    3271                 :         244 :  call wrtout(std_out,' Canonical Atomic Coordinates ')
    3272         [ +  + ]:         887 :  do iatom=1,natom
    3273                 :         643 :    write(msg, '(a,i5,3es18.8)' )' atom',iatom,rcan(1,iatom),rcan(2,iatom),rcan(3,iatom)
    3274                 :         887 :    call wrtout(std_out,msg)
    3275                 :             :  end do
    3276                 :             : 
    3277                 :         244 : end subroutine canat9
    3278                 :             : !!***
    3279                 :             : 
    3280                 :             : !----------------------------------------------------------------------
    3281                 :             : 
    3282                 :             : !!****f* m_dynmat/canct9
    3283                 :             : !!
    3284                 :             : !! NAME
    3285                 :             : !! canct9
    3286                 :             : !!
    3287                 :             : !! FUNCTION
    3288                 :             : !! Convert from canonical coordinates to cartesian coordinates
    3289                 :             : !! a vector defined by its index=ib+natom*(irpt-1)
    3290                 :             : !!
    3291                 :             : !! INPUTS
    3292                 :             : !! acell(3)=length scales by which rprim is to be multiplied
    3293                 :             : !! gprim(3,3)=dimensionless primitive translations in reciprocal space
    3294                 :             : !! index= index of the atom
    3295                 :             : !! natom=number of atoms in unit cell
    3296                 :             : !! nrpt= Number of R points in the Big Box
    3297                 :             : !! rcan(3,natom)=canonical coordinates of atoms
    3298                 :             : !! rprim(3,3)=dimensionless primitive translations in real space
    3299                 :             : !! rpt(3,nrpt)=canonical coordinates of the points in the BigBox.
    3300                 :             : !!
    3301                 :             : !! OUTPUT
    3302                 :             : !! ib=number of the atom in the unit cell
    3303                 :             : !! irpt= number of the unit cell to which belong the atom
    3304                 :             : !! rcart(3)=cartesian coordinate of the atom indexed by index.
    3305                 :             : !!
    3306                 :             : !! SOURCE
    3307                 :             : 
    3308                 :       25503 : subroutine canct9(acell,gprim,ib,index,irpt,natom,nrpt,rcan,rcart,rprim,rpt)
    3309                 :             : 
    3310                 :             : !Arguments -------------------------------
    3311                 :             : !scalars
    3312                 :             :  integer,intent(in) :: index,natom,nrpt
    3313                 :             :  integer,intent(out) :: ib,irpt
    3314                 :             : !arrays
    3315                 :             :  real(dp),intent(in) :: acell(3),gprim(3,3),rcan(3,natom),rprim(3,3)
    3316                 :             :  real(dp),intent(in) :: rpt(3,nrpt)
    3317                 :             :  real(dp),intent(out) :: rcart(3)
    3318                 :             : 
    3319                 :             : !Local variables -------------------------
    3320                 :             : !scalars
    3321                 :             :  integer :: jj
    3322                 :             : !arrays
    3323                 :             :  real(dp) :: xred(3)
    3324                 :             : ! *********************************************************************
    3325                 :             : 
    3326                 :       25503 :  irpt=(index-1)/natom+1
    3327                 :       25503 :  ib=index-natom*(irpt-1)
    3328                 :             : 
    3329                 :             : !Transform the canonical coordinates to reduced coord.
    3330         [ +  + ]:      102012 :  do jj=1,3
    3331                 :             :    xred(jj)=gprim(1,jj)*(rpt(1,irpt)+rcan(1,ib))&
    3332                 :             : &   +gprim(2,jj)*(rpt(2,irpt)+rcan(2,ib))&
    3333                 :      102012 : &   +gprim(3,jj)*(rpt(3,irpt)+rcan(3,ib))
    3334                 :             :  end do
    3335                 :             : 
    3336                 :             : !Then to cartesian coordinates (here the position of the atom b)
    3337         [ +  + ]:      102012 :  do jj=1,3
    3338                 :             :    rcart(jj)=xred(1)*acell(1)*rprim(jj,1)+&
    3339                 :             : &   xred(2)*acell(2)*rprim(jj,2)+&
    3340                 :      102012 : &   xred(3)*acell(3)*rprim(jj,3)
    3341                 :             :  end do
    3342                 :             : 
    3343                 :       25503 : end subroutine canct9
    3344                 :             : !!***
    3345                 :             : 
    3346                 :             : !----------------------------------------------------------------------
    3347                 :             : 
    3348                 :             : !!****f* m_dynmat/chkrp9
    3349                 :             : !! NAME
    3350                 :             : !! chkrp9
    3351                 :             : !!
    3352                 :             : !! FUNCTION
    3353                 :             : !! Check if the rprim used for the definition of the unit cell (in the
    3354                 :             : !! inputs) are consistent with the rprim used in the routine generating
    3355                 :             : !! the Big Box needed to generate the interatomic forces.
    3356                 :             : !!
    3357                 :             : !! INPUTS
    3358                 :             : !! brav=bravais lattice (1 or -1=simple lattice,2=face centered lattice,
    3359                 :             : !!  3=centered lattice,4=hexagonal lattice)
    3360                 :             : !! rprimd(3,3)=dimensional primitive translations for real space (bohr)
    3361                 :             : !!
    3362                 :             : !! OUTPUT
    3363                 :             : !!  (only checking)
    3364                 :             : !!
    3365                 :             : !! SOURCE
    3366                 :             : 
    3367                 :         244 : subroutine chkrp9(brav,rprim)
    3368                 :             : 
    3369                 :             : !Arguments -------------------------------
    3370                 :             : !scalars
    3371                 :             :  integer,intent(in) :: brav
    3372                 :             : !arrays
    3373                 :             :  real(dp),intent(in) :: rprim(3,3)
    3374                 :             : 
    3375                 :             : !Local variables -------------------------
    3376                 :             : !scalars
    3377                 :             :  integer :: ii,jj
    3378                 :             :  character(len=500) :: msg
    3379                 :             : ! *********************************************************************
    3380                 :             : 
    3381         [ +  + ]:         244 :  if (abs(brav)==1) then
    3382                 :             : !  Simple Cubic Lattice No condition in this case !
    3383                 :             :    continue
    3384                 :             : 
    3385         [ +  + ]:          45 :  else if (brav==2) then
    3386                 :             : !  Face Centered Lattice
    3387         [ +  + ]:         120 :    do ii=1,3
    3388         [ +  + ]:         390 :      do jj=1,3
    3389   [ +  +  +  -  :         360 :        if (  ( ii==jj .and. abs(rprim(ii,jj))>tol10) .or. (ii/=jj .and. abs(rprim(ii,jj)-.5_dp)>tol10) ) then
             +  +  -  + ]
    3390                 :             :          write(msg, '(a,a,a,a,a,a,a,a,a,a,a)' )&
    3391                 :           0 :          'The input variable rprim does not correspond to the',ch10,&
    3392                 :           0 :          'fixed rprim to be used with brav=2 and ifcflag=1 :',ch10,&
    3393                 :           0 :          '   0  1/2  1/2',ch10,&
    3394                 :           0 :          '  1/2  0   1/2',ch10,&
    3395                 :           0 :          '  1/2 1/2   0 ',ch10,&
    3396                 :           0 :          'Action: rebuild your DDB by using the latter rprim.'
    3397                 :           0 :          ABI_ERROR(msg)
    3398                 :             :        end if
    3399                 :             :      end do
    3400                 :             :    end do
    3401                 :             : 
    3402         [ +  + ]:          15 :  else if (brav==3) then
    3403                 :             : !  Body Centered Cubic Lattice
    3404         [ +  + ]:          28 :    do ii=1,3
    3405         [ +  + ]:          91 :      do jj=1,3
    3406   [ +  +  +  -  :          84 :        if (  ( ii==jj .and. abs(rprim(ii,jj)+.5_dp)>tol10) .or. (ii/=jj .and. abs(rprim(ii,jj)-.5_dp)>tol10) ) then
             +  +  -  + ]
    3407                 :             :          write(msg, '(a,a,a,a,a,a,a,a,a,a,a)' )&
    3408                 :           0 :          'The input variable rprim does not correspond to the',ch10,&
    3409                 :           0 :          'fixed rprim to be used with brav=3 and ifcflag=1 :',ch10,&
    3410                 :           0 :          '  -1/2  1/2  1/2',ch10,&
    3411                 :           0 :          '   1/2 -1/2  1/2',ch10,&
    3412                 :           0 :          '   1/2  1/2 -1/2',ch10,&
    3413                 :           0 :          'Action: rebuild your DDB by using the latter rprim.'
    3414                 :           0 :          ABI_ERROR(msg)
    3415                 :             :        end if
    3416                 :             :      end do
    3417                 :             :    end do
    3418                 :             : 
    3419         [ +  - ]:           8 :  else if (brav==4) then
    3420                 :             : !  Hexagonal Lattice
    3421                 :             :    if (abs(rprim(1,1)-1.0_dp)>tol10 .or. &
    3422                 :             :        abs(rprim(3,3)-1.0_dp)>tol10 .or. &
    3423                 :             :        abs(rprim(2,1)      )>tol10 .or. &
    3424                 :             :        abs(rprim(3,1)      )>tol10 .or. &
    3425                 :             :        abs(rprim(1,3)      )>tol10 .or. &
    3426                 :             :        abs(rprim(2,3)      )>tol10 .or. &
    3427                 :             :        abs(rprim(3,2)      )>tol10 .or. &
    3428   [ +  -  +  -  :           8 :        abs(rprim(1,2)+0.5_dp)>tol10 .or. &
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  -  + ]
    3429                 :             :        abs(rprim(2,2)-0.5_dp*sqrt(3.0_dp))>tol10 ) then
    3430                 :             :      write(msg, '(a,a,a,a,a,a,a,a,a,a,a)' )&
    3431                 :           0 :       'The input variable rprim does not correspond to the',ch10,&
    3432                 :           0 :       'fixed rprim to be used with brav=4 and ifcflag=1 :',ch10,&
    3433                 :           0 :       '   1      0      0',ch10,&
    3434                 :           0 :       '  -1/2 sqrt[3]/2 0',ch10,&
    3435                 :           0 :       '   0      0      1',ch10,&
    3436                 :           0 :       'Action: rebuild your DDB by using the latter rprim.'
    3437                 :           0 :      ABI_ERROR(msg)
    3438                 :             :    end if
    3439                 :             : 
    3440                 :             :  else
    3441                 :             :    write(msg, '(a,i4,a,a,a,a,a)' )&
    3442                 :           0 :    'The value of brav=',brav,' is not allowed.',ch10,&
    3443                 :           0 :    'Only  -1, 1,2,3 or 4 are allowed.',ch10,&
    3444                 :           0 :    'Action: change the value of brav in your input file.'
    3445                 :           0 :    ABI_ERROR(msg)
    3446                 :             :  end if
    3447                 :             : 
    3448                 :         244 : end subroutine chkrp9
    3449                 :             : !!***
    3450                 :             : 
    3451                 :             : !----------------------------------------------------------------------
    3452                 :             : 
    3453                 :             : !!****f* m_dynmat/dist9
    3454                 :             : !! NAME
    3455                 :             : !! dist9
    3456                 :             : !!
    3457                 :             : !! FUNCTION
    3458                 :             : !! Compute the distance between atoms
    3459                 :             : !!
    3460                 :             : !! INPUTS
    3461                 :             : !! acell(3)=length scales by which rprim is to be multiplied
    3462                 :             : !! dist(natom,natom,nrpt)=distances between atoms
    3463                 :             : !! gprim(3,3)=dimensionless primitive translations in reciprocal space
    3464                 :             : !! natom=number of atoms in unit cell
    3465                 :             : !! nrpt= Number of R points in the Big Box
    3466                 :             : !! rcan(3,natom)=canonical coordinates of atoms
    3467                 :             : !! rprim(3,3)=dimensionless primitive translations in real space
    3468                 :             : !! rpt(3,nrpt)=cartesian coordinates of the points in the BigBox.
    3469                 :             : !!
    3470                 :             : !! OUTPUT
    3471                 :             : !! dist(natom,natom,nrpt)=distances between atoms
    3472                 :             : !!
    3473                 :             : !! SOURCE
    3474                 :             : 
    3475                 :          83 : subroutine dist9(acell,dist,gprim,natom,nrpt,rcan,rprim,rpt)
    3476                 :             : 
    3477                 :             : !Arguments -------------------------------
    3478                 :             : !scalars
    3479                 :             :  integer,intent(in) :: natom,nrpt
    3480                 :             : !arrays
    3481                 :             :  real(dp),intent(in) :: acell(3),gprim(3,3),rcan(3,natom),rprim(3,3)
    3482                 :             :  real(dp),intent(in) :: rpt(3,nrpt)
    3483                 :             :  real(dp),intent(out) :: dist(natom,natom,nrpt)
    3484                 :             : 
    3485                 :             : !Local variables -------------------------
    3486                 :             : !scalars
    3487                 :             :  integer :: ia,ib,ii,irpt
    3488                 :             : !arrays
    3489                 :             :  real(dp) :: ra(3),rb(3),rdiff(3),red(3),rptcar(3),xred(3)
    3490                 :             : ! *********************************************************************
    3491                 :             : 
    3492                 :             : !BIG loop on all generic atoms
    3493         [ +  + ]:         344 :  do ia=1,natom
    3494                 :             :    ! First transform canonical coordinates to reduced coordinates
    3495         [ +  + ]:        1044 :    do ii=1,3
    3496                 :        1044 :      xred(ii)=gprim(1,ii)*rcan(1,ia)+gprim(2,ii)*rcan(2,ia)+gprim(3,ii)*rcan(3,ia)
    3497                 :             :    end do
    3498                 :             :    ! Then to cartesian coordinates
    3499         [ +  + ]:        1044 :    ra(:)=xred(1)*acell(1)*rprim(:,1)+xred(2)*acell(2)*rprim(:,2)+xred(3)*acell(3)*rprim(:,3)
    3500         [ +  + ]:        1727 :    do ib=1,natom
    3501         [ +  + ]:        5532 :      do ii=1,3
    3502                 :        5532 :        xred(ii)=gprim(1,ii)*rcan(1,ib)+gprim(2,ii)*rcan(2,ib)+gprim(3,ii)*rcan(3,ib)
    3503                 :             :      end do
    3504         [ +  + ]:        5532 :      do ii=1,3
    3505                 :        5532 :        rb(ii)=xred(1)*acell(1)*rprim(ii,1)+xred(2)*acell(2)*rprim(ii,2)+xred(3)*acell(3)*rprim(ii,3)
    3506                 :             :      end do
    3507         [ +  + ]:      885889 :      do irpt=1,nrpt
    3508                 :             :        ! First transform it to reduced coordinates
    3509         [ +  + ]:     3536980 :        do ii=1,3
    3510                 :     3536980 :          red(ii)=gprim(1,ii)*rpt(1,irpt)+gprim(2,ii)*rpt(2,irpt)+gprim(3,ii)*rpt(3,irpt)
    3511                 :             :        end do
    3512                 :             :        ! Then to cartesian coordinates
    3513         [ +  + ]:     3536980 :        do ii=1,3
    3514                 :     3536980 :          rptcar(ii)=red(1)*acell(1)*rprim(ii,1)+red(2)*acell(2)*rprim(ii,2)+red(3)*acell(3)*rprim(ii,3)
    3515                 :             :        end do
    3516         [ +  + ]:     3536980 :        do ii=1,3
    3517                 :     3536980 :          rdiff(ii)=-rptcar(ii)+ra(ii)-rb(ii)
    3518                 :             :        end do
    3519                 :      885628 :        dist(ia,ib,irpt)=(rdiff(1)**2+rdiff(2)**2+rdiff(3)**2)**0.5
    3520                 :             :      end do
    3521                 :             :    end do
    3522                 :             :  end do
    3523                 :             : 
    3524                 :          83 : end subroutine dist9
    3525                 :             : !!***
    3526                 :             : 
    3527                 :             : !----------------------------------------------------------------------
    3528                 :             : 
    3529                 :             : !!****f* m_dynmat/ftifc_q2r
    3530                 :             : !!
    3531                 :             : !! NAME
    3532                 :             : !! ftifc_q2r
    3533                 :             : !!
    3534                 :             : !! FUNCTION
    3535                 :             : !!  Generates the Fourier transform of the dynamical matrices
    3536                 :             : !!  to obtain interatomic forces (real space).
    3537                 :             : !!
    3538                 :             : !! INPUTS
    3539                 :             : !! dynmat(2,3,natom,3,natom,nqpt)= Dynamical matrices coming from the Derivative Data Base
    3540                 :             : !! gprim(3,3)= Normalized coordinates in reciprocal space
    3541                 :             : !! natom= Number of atoms in the unit cell
    3542                 :             : !! nqpt= Number of q points in the Brillouin zone
    3543                 :             : !! nrpt= Number of R points in the Big Box
    3544                 :             : !! rpt(3,nprt)= Canonical coordinates of the R points in the unit cell
    3545                 :             : !!           These coordinates are normalized (=> * acell(3)!!)
    3546                 :             : !! spqpt(3,nqpt)= Reduced coordinates of the q vectors in reciprocal space
    3547                 :             : !! comm=MPI communicator.
    3548                 :             : !!
    3549                 :             : !! OUTPUT
    3550                 :             : !! atmfrc(3,natom,3,natom,nrpt)= Interatomic Forces in real space.
    3551                 :             : !!
    3552                 :             : !! SOURCE
    3553                 :             : 
    3554                 :         244 : subroutine ftifc_q2r(atmfrc,dynmat,gprim,natom,nqpt,nrpt,rpt,spqpt,comm)
    3555                 :             : 
    3556                 :             : !Arguments -------------------------------
    3557                 :             : !scalars
    3558                 :             :  integer,intent(in) :: natom,nqpt,nrpt,comm
    3559                 :             : !arrays
    3560                 :             :  real(dp),intent(in) :: gprim(3,3),rpt(3,nrpt),spqpt(3,nqpt)
    3561                 :             :  real(dp),intent(out) :: atmfrc(3,natom,3,natom,nrpt)
    3562                 :             :  real(dp),intent(in) :: dynmat(2,3,natom,3,natom,nqpt)
    3563                 :             : 
    3564                 :             : !Local variables -------------------------
    3565                 :             : !scalars
    3566                 :             :  integer :: ia,ib,iqpt,irpt,mu,nu,nprocs,my_rank,ierr
    3567                 :             :  real(dp) :: im,kr,re
    3568                 :             : !arrays
    3569                 :             :  real(dp) :: kk(3)
    3570                 :             : ! *********************************************************************
    3571                 :             : 
    3572                 :         244 :  nprocs = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
    3573                 :             : 
    3574                 :             :  ! Interatomic Forces from Dynamical Matrices
    3575   [ +  +  +  +  :   112985605 :  atmfrc = zero
          +  +  +  +  +  
                      + ]
    3576         [ +  + ]:      557469 :  do irpt=1,nrpt
    3577         [ +  + ]:      557225 :    if (mod(irpt, nprocs) /= my_rank) cycle ! mpi-parallelism
    3578         [ +  + ]:   163118444 :    do iqpt=1,nqpt
    3579                 :             : 
    3580                 :             :      ! Calculation of the k coordinates in Normalized Reciprocal coordinates
    3581   [ +  +  +  + ]:  2113328347 :      kk(:) = matmul(gprim, spqpt(:, iqpt))
    3582                 :             : 
    3583                 :             :      ! Product of k and r
    3584         [ +  + ]:   650254876 :      kr=dot_product(kk,rpt(:,irpt))
    3585                 :             : 
    3586                 :             :      ! Get the phase factor
    3587                 :   162563719 :      re=cos(two_pi*kr)
    3588                 :   162563719 :      im=sin(two_pi*kr)
    3589                 :             : 
    3590                 :             :      ! Now, big inner loops on atoms and directions
    3591                 :             :      ! The indices are ordered to give better speed
    3592         [ +  + ]:   756263335 :      do ib=1,natom
    3593         [ +  + ]:  2535133283 :        do nu=1,3
    3594         [ +  + ]: 12396638707 :          do ia=1,natom
    3595         [ +  + ]: 41875703745 :            do mu=1,3
    3596                 :             :              ! Real part of the interatomic forces
    3597                 :             :              atmfrc(mu,ia,nu,ib,irpt)=atmfrc(mu,ia,nu,ib,irpt) &
    3598                 :             :               +re*dynmat(1,mu,ia,nu,ib,iqpt)&
    3599                 : 40096276572 :               +im*dynmat(2,mu,ia,nu,ib,iqpt)
    3600                 :             :              !The imaginary part should be equal to zero !!!!!!
    3601                 :             :              !atmfrc(2,mu,ia,nu,ib,irpt)=atmfrc(2,mu,ia,nu,ib,irpt) &
    3602                 :             :              !          +re*dynmat(2,mu,ia,nu,ib,iqpt) &
    3603                 :             :              !          -im*dynmat(1,mu,ia,nu,ib,iqpt)
    3604                 :             :            end do
    3605                 :             :          end do
    3606                 :             :        end do
    3607                 :             :      end do
    3608                 :             : 
    3609                 :             :    end do
    3610                 :             :  end do
    3611                 :             : 
    3612                 :         244 :  call xmpi_sum(atmfrc, comm, ierr)
    3613                 :             :  !The sumifc has to be weighted by a normalization factor of 1/nqpt
    3614   [ +  +  +  +  :   112985605 :  atmfrc = atmfrc/nqpt
          +  +  +  +  +  
                      + ]
    3615                 :             : 
    3616                 :         244 : end subroutine ftifc_q2r
    3617                 :             : !!***
    3618                 :             : 
    3619                 :             : !----------------------------------------------------------------------
    3620                 :             : 
    3621                 :             : !!****f* m_dynmat/ftifc_r2q
    3622                 :             : !!
    3623                 :             : !! NAME
    3624                 :             : !! ftifc_r2q
    3625                 :             : !!
    3626                 :             : !! FUNCTION
    3627                 :             : !! Generates the Fourier transform of the interatomic forces
    3628                 :             : !! to obtain dynamical matrices in reciprocal space: R --> q.
    3629                 :             : !!
    3630                 :             : !! INPUTS
    3631                 :             : !! atmfrc(3,natom,3,natom,nrpt)= Interatomic Forces in real space
    3632                 :             : !! gprim(3,3)= Normalized coordinates in reciprocal space
    3633                 :             : !! natom= Number of atoms in the unit cell
    3634                 :             : !! nqpt= Number of q points in the Brillouin zone
    3635                 :             : !! nrpt= Number of R points in the Big Box
    3636                 :             : !! rpt(3,nprt)= Canonical coordinates of the R points in the unit cell
    3637                 :             : !!   These coordinates are normalized (=> * acell(3)!!)
    3638                 :             : !! spqpt(3,nqpt)= Reduced coordinates of the q vectors in reciprocal space
    3639                 :             : !! wghatm(natom,natom,nrpt)= Weights associated to a pair of atoms and to a R vector
    3640                 :             : !! comm: MPI communicator
    3641                 :             : !!
    3642                 :             : !! OUTPUT
    3643                 :             : !! dynmat(2,3,natom,3,natom,nqpt)= Dynamical matrices coming from the Derivative Data Base
    3644                 :             : !!
    3645                 :             : !! SOURCE
    3646                 :             : 
    3647                 :      229789 : subroutine ftifc_r2q(atmfrc, dynmat, gprim, natom, nqpt, nrpt, rpt, spqpt, wghatm, comm)
    3648                 :             : 
    3649                 :             : !Arguments -------------------------------
    3650                 :             : !scalars
    3651                 :             :  integer,intent(in) :: natom,nqpt,nrpt,comm
    3652                 :             : !arrays
    3653                 :             :  real(dp),intent(in) :: gprim(3,3),rpt(3,nrpt),spqpt(3,nqpt)
    3654                 :             :  real(dp),intent(in) :: wghatm(natom,natom,nrpt)
    3655                 :             :  real(dp),intent(in) :: atmfrc(3,natom,3,natom,nrpt)
    3656                 :             :  real(dp),intent(out) :: dynmat(2,3,natom,3,natom,nqpt)
    3657                 :             : 
    3658                 :             : !Local variables -------------------------
    3659                 :             : !scalars
    3660                 :             :  integer :: ia,ib,iqpt,irpt,mu,nu,cnt,my_rank,nprocs, ierr
    3661                 :             :  real(dp) :: facti,factr,im,kr,re
    3662                 :             :  !real(dp) : w(2, natom, natom)
    3663                 :             : !arrays
    3664                 :             :  real(dp) :: kk(3)
    3665                 :             : ! *********************************************************************
    3666                 :             : 
    3667                 :      229789 :  my_rank = xmpi_comm_rank(comm); nprocs = xmpi_comm_size(comm)
    3668   [ +  +  +  +  :    41524548 :  dynmat = zero; cnt = 0
          +  +  +  +  +  
                +  +  + ]
    3669                 :             : 
    3670                 :             :  ! MG: This is an hotspot. I don'tknow whether one should rewrite with BLAS1 dot or not.
    3671                 :             :  ! Note, however, that simply removing the check on the weights inside the loop over atoms.
    3672                 :             :  ! leads to a non-negligible speedup with intel (~30% if dipdip -1 is used)
    3673         [ +  + ]:      459578 :  do iqpt=1,nqpt
    3674                 :             : 
    3675                 :             :    ! Calculation of the k coordinates in Normalized Reciprocal coordinates
    3676   [ +  +  +  + ]:     2987257 :    kk(:) = matmul(gprim, spqpt(:, iqpt))
    3677                 :             : 
    3678         [ +  + ]:    94472937 :    do irpt=1,nrpt
    3679         [ +  - ]:    94013359 :      cnt = cnt + 1; if (mod(cnt, nprocs) /= my_rank) cycle ! MPI parallelism.
    3680                 :             : 
    3681                 :             :      ! k.R
    3682         [ +  + ]:   376053436 :      kr=dot_product(kk,rpt(:,irpt))
    3683                 :             :      ! Get phase factor
    3684                 :    94013359 :      re = cos(two_pi*kr); im = sin(two_pi*kr)
    3685                 :             : 
    3686                 :             :      ! Inner loop on atoms and directions
    3687         [ +  + ]:   308988825 :      do ib=1,natom
    3688         [ +  + ]:  1094001443 :        do ia=1,natom
    3689                 :             :          !if (abs(wghatm(ia,ib,irpt)) > tol10) then  ! Commented by MG
    3690                 :   785242407 :            factr = re * wghatm(ia,ib,irpt)
    3691                 :   785242407 :            facti = im * wghatm(ia,ib,irpt)
    3692         [ +  + ]:  3355715305 :            do nu=1,3
    3693         [ +  + ]: 10208151291 :              do mu=1,3
    3694                 :             :                ! Real and imaginary part of the dynamical matrices
    3695                 :             :                ! Atmfrc should be real
    3696                 :  7067181663 :                dynmat(1,mu,ia,nu,ib,iqpt) = dynmat(1,mu,ia,nu,ib,iqpt) + factr * atmfrc(mu,ia,nu,ib,irpt)
    3697                 :  9422908884 :                dynmat(2,mu,ia,nu,ib,iqpt) = dynmat(2,mu,ia,nu,ib,iqpt) + facti * atmfrc(mu,ia,nu,ib,irpt)
    3698                 :             :              end do
    3699                 :             :            end do
    3700                 :             :          !end if
    3701                 :             :        end do
    3702                 :             :      end do
    3703                 :             : 
    3704                 :             :      ! MG: New version: I don't know if it's faster.
    3705                 :             :      !w(1,:,:) = re * wghatm(:,:,irpt)
    3706                 :             :      !w(2,:,:) = im * wghatm(:,:,irpt)
    3707                 :             :      !do ib=1,natom
    3708                 :             :      !  do nu=1,3
    3709                 :             :      !    do ia=1,natom
    3710                 :             :      !      do mu=1,3
    3711                 :             :      !        ! Real and imaginary part of the dynamical matrices
    3712                 :             :      !        ! Atmfrc should be real
    3713                 :             :      !        dynmat(1,mu,ia,nu,ib,iqpt) = dynmat(1,mu,ia,nu,ib,iqpt) + w(1,ia,ib) * atmfrc(mu,ia,nu,ib,irpt)
    3714                 :             :      !        dynmat(2,mu,ia,nu,ib,iqpt) = dynmat(2,mu,ia,nu,ib,iqpt) + w(2,ia,ib) * atmfrc(mu,ia,nu,ib,irpt)
    3715                 :             :      !     end do
    3716                 :             :      !    end do
    3717                 :             :      !  end do
    3718                 :             :      !end do
    3719                 :             : 
    3720                 :             :    end do
    3721                 :             :  end do
    3722                 :             : 
    3723         [ -  + ]:      229789 :  if (nprocs > 1) call xmpi_sum(dynmat, comm, ierr)
    3724                 :             : 
    3725                 :      229789 : end subroutine ftifc_r2q
    3726                 :             : !!***
    3727                 :             : 
    3728                 :             : !----------------------------------------------------------------------
    3729                 :             : 
    3730                 :             : !!****f* m_dynmat/dynmat_dq
    3731                 :             : !!
    3732                 :             : !! NAME
    3733                 :             : !! dynmat_dq
    3734                 :             : !!
    3735                 :             : !! FUNCTION
    3736                 :             : !!  Compute the derivative D(q)/dq of the dynamical matrix via Fourier transform
    3737                 :             : !!  of the interatomic forces
    3738                 :             : !!
    3739                 :             : !! INPUTS
    3740                 :             : !! qpt(3)= Reduced coordinates of the q vector in reciprocal space
    3741                 :             : !! natom= Number of atoms in the unit cell
    3742                 :             : !! gprim(3,3)= Normalized coordinates in reciprocal space
    3743                 :             : !! nrpt= Number of R points in the Big Box
    3744                 :             : !! rpt(3,nprt)= Canonical coordinates of the R points in the unit cell
    3745                 :             : !!   These coordinates are normalized (=> * acell(3)!!)
    3746                 :             : !! atmfrc(3,natom,3,natom,nrpt)= Interatomic Forces in real space
    3747                 :             : !! wghatm(natom,natom,nrpt)= Weights associated to a pair of atoms and to a R vector
    3748                 :             : !!
    3749                 :             : !! OUTPUT
    3750                 :             : !! dddq(2,3,natom,3,natom,3)= Derivate of the dynamical matrix in cartesian coordinates.
    3751                 :             : !!  The three directions are stored in the last dimension.
    3752                 :             : !!  These coordinates are normalized (=> * acell(3)!!)
    3753                 :             : !!
    3754                 :             : !! SOURCE
    3755                 :             : 
    3756                 :      155875 : subroutine dynmat_dq(qpt,natom,gprim,nrpt,rpt,atmfrc,wghatm,dddq)
    3757                 :             : 
    3758                 :             : !Arguments -------------------------------
    3759                 :             : !scalars
    3760                 :             :  integer,intent(in) :: natom,nrpt
    3761                 :             : !arrays
    3762                 :             :  real(dp),intent(in) :: gprim(3,3),rpt(3,nrpt),qpt(3)
    3763                 :             :  real(dp),intent(in) :: wghatm(natom,natom,nrpt)
    3764                 :             :  real(dp),intent(in) :: atmfrc(3,natom,3,natom,nrpt)
    3765                 :             :  real(dp),intent(out) :: dddq(2,3,natom,3,natom,3)
    3766                 :             : 
    3767                 :             : !Local variables -------------------------
    3768                 :             : !scalars
    3769                 :             :  integer :: ia,ib,irpt,mu,nu,ii
    3770                 :             :  real(dp) :: im,kr,re
    3771                 :             : !arrays
    3772                 :             :  real(dp) :: kk(3),fact(2,3)
    3773                 :             : ! *********************************************************************
    3774                 :             : 
    3775   [ +  +  +  +  :    46767346 :  dddq = zero
          +  +  +  +  +  
                +  +  + ]
    3776         [ +  + ]:    71954014 :  do irpt=1,nrpt
    3777                 :             :    ! Calculation of the k coordinates in Normalized Reciprocal coordinates
    3778   [ +  +  +  + ]:   933375807 :    kk(:) = matmul(gprim, qpt)
    3779                 :             : 
    3780                 :             :    ! Product of k and r
    3781         [ +  + ]:   287192556 :    kr=dot_product(kk,rpt(:,irpt))
    3782                 :             : 
    3783                 :             :    ! Get phase factor
    3784                 :    71798139 :    re=cos(two_pi*kr); im=sin(two_pi*kr)
    3785                 :             : 
    3786                 :             :    ! Inner loop on atoms and directions
    3787         [ +  + ]:   199458763 :    do ib=1,natom
    3788         [ +  + ]:   462485909 :      do ia=1,natom
    3789         [ +  + ]:   390687770 :        if (abs(wghatm(ia,ib,irpt))>1.0d-10) then
    3790                 :             :          ! take into account rotation due to i.
    3791         [ +  + ]:   885900748 :          fact(1,:) = -im * wghatm(ia,ib,irpt) * rpt(:,irpt)
    3792         [ +  + ]:   885900748 :          fact(2,:) =  re * wghatm(ia,ib,irpt) * rpt(:,irpt)
    3793         [ +  + ]:   885900748 :          do nu=1,3
    3794         [ +  + ]:  2879177431 :            do mu=1,3
    3795                 :             :              ! Real and imaginary part of the dynamical matrices
    3796                 :             :              ! Atmfrc should be real
    3797         [ +  + ]:  8637532293 :              do ii=1,3
    3798                 :  5979830049 :                dddq(1,mu,ia,nu,ib,ii) = dddq(1,mu,ia,nu,ib,ii) + fact(1,ii) * atmfrc(mu,ia,nu,ib,irpt)
    3799                 :  7973106732 :                dddq(2,mu,ia,nu,ib,ii) = dddq(2,mu,ia,nu,ib,ii) + fact(2,ii) * atmfrc(mu,ia,nu,ib,irpt)
    3800                 :             :              end do
    3801                 :             :            end do
    3802                 :             :          end do
    3803                 :             :        end if
    3804                 :             :      end do
    3805                 :             :    end do
    3806                 :             :  end do
    3807                 :      155875 : end subroutine dynmat_dq
    3808                 :             : !!***
    3809                 :             : 
    3810                 :             : !----------------------------------------------------------------------
    3811                 :             : 
    3812                 :             : !!****f* m_dynmat/ifclo9
    3813                 :             : !! NAME
    3814                 :             : !! ifclo9
    3815                 :             : !!
    3816                 :             : !! FUNCTION
    3817                 :             : !! Convert from cartesian coordinates to local coordinates
    3818                 :             : !! the 3*3 interatomic force constant matrix
    3819                 :             : !!
    3820                 :             : !! INPUTS
    3821                 :             : !! ifccar(3,3)= matrix of interatomic force constants in cartesian
    3822                 :             : !!  coordinates
    3823                 :             : !! vect1(3)= cartesian coordinates of the first local vector
    3824                 :             : !! vect2(3)= cartesian coordinates of the second local vector
    3825                 :             : !! vect3(3)= cartesian coordinates of the third local vector
    3826                 :             : !!
    3827                 :             : !! OUTPUT
    3828                 :             : !! ifcloc(3,3)= matrix of interatomic force constants in local coordinates
    3829                 :             : !!
    3830                 :             : !! SOURCE
    3831                 :             : 
    3832                 :       34357 : subroutine ifclo9(ifccar,ifcloc,vect1,vect2,vect3)
    3833                 :             : 
    3834                 :             : !Arguments -------------------------------
    3835                 :             : !arrays
    3836                 :             :  real(dp),intent(in) :: ifccar(3,3),vect1(3),vect2(3),vect3(3)
    3837                 :             :  real(dp),intent(out) :: ifcloc(3,3)
    3838                 :             : 
    3839                 :             : !Local variables -------------------------
    3840                 :             : !scalars
    3841                 :             :  integer :: ii,jj
    3842                 :             : !arrays
    3843                 :             :  real(dp) :: work(3,3)
    3844                 :             : ! *********************************************************************
    3845                 :             : 
    3846         [ +  + ]:      137428 :  do jj=1,3
    3847         [ +  + ]:      412284 :    do ii=1,3
    3848                 :      412284 :      work(jj,ii)=zero
    3849                 :             :    end do
    3850         [ +  + ]:      446641 :    do ii=1,3
    3851                 :      309213 :      work(jj,1)=work(jj,1)+ifccar(jj,ii)*vect1(ii)
    3852                 :      309213 :      work(jj,2)=work(jj,2)+ifccar(jj,ii)*vect2(ii)
    3853                 :      412284 :      work(jj,3)=work(jj,3)+ifccar(jj,ii)*vect3(ii)
    3854                 :             :    end do
    3855                 :             :  end do
    3856                 :             : 
    3857         [ +  + ]:      137428 :  do jj=1,3
    3858         [ +  + ]:      412284 :    do ii=1,3
    3859                 :      412284 :      ifcloc(ii,jj)=zero
    3860                 :             :    end do
    3861         [ +  + ]:      446641 :    do ii=1,3
    3862                 :      309213 :      ifcloc(1,jj)=ifcloc(1,jj)+vect1(ii)*work(ii,jj)
    3863                 :      309213 :      ifcloc(2,jj)=ifcloc(2,jj)+vect2(ii)*work(ii,jj)
    3864                 :      412284 :      ifcloc(3,jj)=ifcloc(3,jj)+vect3(ii)*work(ii,jj)
    3865                 :             :    end do
    3866                 :             :  end do
    3867                 :             : 
    3868                 :       34357 : end subroutine ifclo9
    3869                 :             : !!***
    3870                 :             : 
    3871                 :             : !----------------------------------------------------------------------
    3872                 :             : 
    3873                 :             : !!****f* m_dynmat/wght9
    3874                 :             : !! NAME
    3875                 :             : !! wght9
    3876                 :             : !!
    3877                 :             : !! FUNCTION
    3878                 :             : !! Generates a weight to each R point of the Big Box and for each pair of atoms
    3879                 :             : !! For each R points included in the space generates by moving
    3880                 :             : !! the unit cell around each atom; the weight will be one.
    3881                 :             : !! Border conditions are provided.
    3882                 :             : !! The R points outside the chosen space will have a 0 weight.
    3883                 :             : !!
    3884                 :             : !! INPUTS
    3885                 :             : !! brav = Bravais lattice (1 or -1=S.C.;2=F.C.C.;4=Hex. -1 is for old algo to find weights, =1 is for Wigner-Seitz algo)
    3886                 :             : !! gprim(3,3)= Normalized coordinates in reciprocal space
    3887                 :             : !! natom= Number of atoms in the unit cell
    3888                 :             : !! ngqpt(6)= Numbers used to sample the Brillouin zone
    3889                 :             : !! nqpt= Number of q points used in the homogeneous grid
    3890                 :             : !!  sampling the Brillouin zone
    3891                 :             : !! nqshft=number of shift vectors in the repeated cell
    3892                 :             : !! nrpt=Number of R points in the Big Box
    3893                 :             : !! qshft(3,nqshft)=vectors that will be used to determine
    3894                 :             : !!  the shifts from (0. 0. 0.)
    3895                 :             : !! rcan(3,natom)=Atomic position in canonical coordinates
    3896                 :             : !! rpt(3,nprt)=Canonical coordinates of the R points in the unit cell
    3897                 :             : !!  These coordinates are normalized (=> * acell(3))
    3898                 :             : !! rprimd(3,3)=dimensional primitive translations for real space (bohr)
    3899                 :             : !! toldist= Tolerance on the distance between two R points.
    3900                 :             : !!
    3901                 :             : !! OUTPUT
    3902                 :             : !! wghatm(natom,natom,nrpt)= Weight associated to the couple of atoms and the R vector
    3903                 :             : !!  The vector r(atom2)-r(atom1)+rpt should be inside the moving box
    3904                 :             : !! r_inscribed_sphere= The radius of the sphere inscribed inside the big box.
    3905                 :             : !! ngqpt(6)= can be modified
    3906                 :             : !!
    3907                 :             : !! SOURCE
    3908                 :             : 
    3909                 :         245 : subroutine wght9(brav,gprim,natom,ngqpt,nqpt,nqshft,nrpt,qshft,rcan,rpt,rprimd,toldist,r_inscribed_sphere,wghatm,ierr)
    3910                 :             : 
    3911                 :             : !Arguments -------------------------------
    3912                 :             : !scalars
    3913                 :             :  integer,intent(in) :: brav,natom,nqpt,nqshft,nrpt
    3914                 :             :  integer,intent(out) :: ierr
    3915                 :             :  real(dp),intent(out) :: r_inscribed_sphere
    3916                 :             :  real(dp),intent(in) :: toldist
    3917                 :             : !arrays
    3918                 :             :  integer,intent(inout) :: ngqpt(9)
    3919                 :             :  real(dp),intent(in) :: gprim(3,3),qshft(3,4),rcan(3,natom),rpt(3,nrpt),rprimd(3,3)
    3920                 :             :  real(dp),intent(out) :: wghatm(natom,natom,nrpt)
    3921                 :             : 
    3922                 :             : !Local variables -------------------------
    3923                 :             : !scalars
    3924                 :             :  integer :: ia,ib,ii,jj,kk,iqshft,irpt,jqshft,nbordh,tok,nptws,nreq,idir
    3925                 :             :  real(dp) :: factor,sumwght,normsq,proj
    3926                 :             :  character(len=500) :: msg
    3927                 :             : !arrays
    3928                 :             :  integer :: nbord(9)
    3929                 :             :  real(dp) :: rdiff(9),red(3,3),ptws(4, 729),pp(3),rdiff_tmp(3)
    3930                 :             : ! *********************************************************************
    3931                 :             : 
    3932                 :         245 :  ierr = 0
    3933                 :             : 
    3934                 :             :  ! First analyze the vectors qshft
    3935         [ +  + ]:         245 :  if (nqshft /= 1) then
    3936                 :             : 
    3937         [ -  + ]:           6 :    if (brav == 4) then
    3938                 :             :      write(msg,'(3a,i0,3a)' )&
    3939                 :           0 :      'For the time being, only nqshft=1',ch10,&
    3940                 :           0 :      'is allowed with brav=4, while it is nqshft=',nqshft,'.',ch10,&
    3941                 :           0 :      'Action: in the input file, correct either brav or nqshft.'
    3942                 :           0 :      ABI_ERROR(msg)
    3943                 :             :    end if
    3944                 :             : 
    3945         [ +  + ]:           6 :    if (nqshft == 2) then
    3946                 :             :      ! Make sure that the q vectors form a BCC lattice
    3947         [ +  + ]:           8 :      do ii=1,3
    3948         [ -  + ]:           8 :        if(abs(abs(qshft(ii,1)-qshft(ii,2))-.5_dp)>1.d-10)then
    3949                 :             :          write(msg, '(a,a,a,a,a,a,a)' )&
    3950                 :           0 :          'The test of the q1shft vectors shows that they',ch10,&
    3951                 :           0 :          'do not generate a body-centered lattice, which',ch10,&
    3952                 :           0 :          'is mandatory for nqshft=2.',ch10,&
    3953                 :           0 :          'Action: change the q1shft vectors in your input file.'
    3954                 :           0 :          ABI_ERROR(msg)
    3955                 :             :        end if
    3956                 :             :      end do
    3957         [ +  - ]:           4 :    else if (nqshft == 4) then
    3958                 :             :      ! Make sure that the q vectors form a FCC lattice
    3959         [ +  + ]:          16 :      do iqshft=1,3
    3960         [ +  + ]:          40 :        do jqshft=iqshft+1,4
    3961                 :             :          tok=0
    3962         [ +  + ]:          96 :          do ii=1,3
    3963                 :             :            ! Test on the presence of a +-0.5 difference
    3964         [ +  + ]:          72 :            if(abs(abs(qshft(ii,iqshft)-qshft(ii,jqshft))-.5_dp) <1.d-10) tok=tok+1
    3965                 :             :            ! Test on the presence of a 0 or +-1.0 difference
    3966         [ +  + ]:          72 :            if(abs(abs(qshft(ii,iqshft)-qshft(ii,jqshft))-1._dp) <1.d-10  .or.&
    3967         [ +  - ]:         120 :               abs(qshft(ii,iqshft)-qshft(ii,jqshft)) < 1.d-10) tok=tok+4
    3968                 :             :          end do
    3969                 :             :          ! Test 1 should be satisfied twice, and test 2 once
    3970         [ -  + ]:          36 :          if(tok/=6)then
    3971                 :             :            write(msg, '(7a)' )&
    3972                 :           0 :            'The test of the q1shft vectors shows that they',ch10,&
    3973                 :           0 :            'do not generate a face-centered lattice, which',ch10,&
    3974                 :           0 :            'is mandatory for nqshft=4.',ch10,&
    3975                 :           0 :            'Action: change the q1shft vectors in your input file.'
    3976                 :           0 :            ABI_ERROR(msg)
    3977                 :             :          end if
    3978                 :             :        end do
    3979                 :             :      end do
    3980                 :             :    else
    3981                 :             :      write(msg, '(a,i4,3a)' )&
    3982                 :           0 :      'nqshft must be 1, 2 or 4. It is nqshft=',nqshft,'.',ch10,&
    3983                 :           0 :      'Action: change nqshft in your input file.'
    3984                 :           0 :      ABI_ERROR(msg)
    3985                 :             :    end if
    3986                 :             :  end if
    3987                 :             : 
    3988                 :         245 :  factor=0.5_dp
    3989         [ +  + ]:         245 :  if(brav==2 .or. brav==3) factor=0.25_dp
    3990         [ +  + ]:         245 :  if(nqshft/=1)factor=factor*2
    3991                 :             : 
    3992         [ +  + ]:         245 :  if (brav==1) then
    3993                 :             :    ! Does not support multiple shifts
    3994         [ -  + ]:         197 :    if (nqshft/=1) then
    3995                 :           0 :      ABI_ERROR('This version of the weights does not support nqshft/=1.')
    3996                 :             :    end if
    3997                 :             : 
    3998                 :             :    ! Find the points of the lattice given by ngqpt*acell. These are used to define
    3999                 :             :    ! a Wigner-Seitz cell around the origin. The origin is excluded from the list.
    4000                 :             :    ! TODO : in principle this should be only -1 to +1 for ii jj kk!
    4001                 :             :    nptws=0
    4002         [ +  + ]:        1182 :    do ii=-2,2
    4003         [ +  + ]:        6107 :      do jj=-2,2
    4004         [ +  + ]:       30535 :        do kk=-2,2
    4005         [ +  + ]:       98500 :          do idir=1,3
    4006                 :       98500 :            pp(idir)=ii*ngqpt(1)*rprimd(idir,1)+ jj*ngqpt(2)*rprimd(idir,2)+ kk*ngqpt(3)*rprimd(idir,3)
    4007                 :             :          end do
    4008                 :       24625 :          normsq = pp(1)*pp(1)+pp(2)*pp(2)+pp(3)*pp(3)
    4009         [ +  + ]:       29550 :          if (normsq > tol6) then
    4010                 :       24428 :            nptws = nptws + 1
    4011         [ +  + ]:       97712 :            ptws(:3,nptws) = pp(:)
    4012                 :       24428 :            ptws(4,nptws) = half*normsq
    4013                 :             :          end if
    4014                 :             :        end do
    4015                 :             :      end do
    4016                 :             :    end do
    4017                 :             :  end if ! end new_wght
    4018                 :             :  !write(std_out,*)'factor,ngqpt',factor,ngqpt(1:3)
    4019                 :             : 
    4020   [ +  +  +  +  :        4655 :  r_inscribed_sphere = sum((matmul(rprimd(:,:),ngqpt(1:3)))**2)
             +  +  +  + ]
    4021         [ +  + ]:         980 :  do ii=-1,1
    4022         [ +  + ]:        3185 :    do jj=-1,1
    4023         [ +  + ]:        9555 :      do kk=-1,1
    4024         [ +  + ]:        6615 :        if (ii==0 .and. jj==0 .and. kk==0) cycle
    4025         [ +  + ]:       25480 :        do idir=1,3
    4026                 :       25480 :          pp(idir)=ii*ngqpt(1)*rprimd(idir,1)+ jj*ngqpt(2)*rprimd(idir,2)+ kk*ngqpt(3)*rprimd(idir,3)
    4027                 :             :        end do
    4028                 :        6370 :        normsq = pp(1)*pp(1)+pp(2)*pp(2)+pp(3)*pp(3)
    4029                 :        8820 :        r_inscribed_sphere = min(r_inscribed_sphere, normsq)
    4030                 :             :      end do
    4031                 :             :    end do
    4032                 :             :  end do
    4033                 :         245 :  r_inscribed_sphere = sqrt(r_inscribed_sphere)
    4034                 :             : 
    4035                 :             : 
    4036                 :             : !Begin the big loop on ia and ib
    4037         [ +  + ]:         892 :  do ia=1,natom
    4038         [ +  + ]:        3679 :    do ib=1,natom
    4039                 :             : 
    4040                 :             :      ! Simple Lattice
    4041         [ +  + ]:        2787 :      if (abs(brav)==1) then
    4042                 :             :        ! In this case, it is better to work in reduced coordinates
    4043                 :             :        ! As rcan is in canonical coordinates, => multiplication by gprim
    4044         [ +  + ]:        9568 :        do ii=1,3
    4045                 :        7176 :          red(1,ii)=  rcan(1,ia)*gprim(1,ii) +rcan(2,ia)*gprim(2,ii) +rcan(3,ia)*gprim(3,ii)
    4046                 :        9568 :          red(2,ii)=  rcan(1,ib)*gprim(1,ii) +rcan(2,ib)*gprim(2,ii) +rcan(3,ib)*gprim(3,ii)
    4047                 :             :        end do
    4048                 :             :      end if
    4049                 :             : 
    4050         [ +  + ]:     8896656 :      do irpt=1,nrpt
    4051                 :             : 
    4052                 :             :        ! Initialization of the weights to 1.0
    4053                 :     8893222 :        wghatm(ia,ib,irpt)=1.0_dp
    4054                 :             : 
    4055                 :             :        ! Compute the difference vector
    4056                 :             : 
    4057                 :             :        ! Simple Cubic Lattice
    4058         [ +  + ]:     8893222 :        if (abs(brav)==1) then
    4059                 :             :          ! Change of rpt to reduced coordinates
    4060         [ +  + ]:    33769080 :          do ii=1,3
    4061                 :    25326810 :            red(3,ii)=  rpt(1,irpt)*gprim(1,ii) +rpt(2,irpt)*gprim(2,ii) +rpt(3,irpt)*gprim(3,ii)
    4062                 :    33769080 :            rdiff(ii)=red(2,ii)-red(1,ii)+red(3,ii)
    4063                 :             :          end do
    4064         [ +  + ]:     8442270 :          if (brav==1) then
    4065                 :             :            ! rdiff in cartesian coordinates
    4066         [ +  + ]:    33072784 :            do ii=1,3
    4067                 :    33072784 :              rdiff_tmp(ii)=rdiff(1)*rprimd(ii,1)+rdiff(2)*rprimd(ii,2)+rdiff(3)*rprimd(ii,3)
    4068                 :             :            end do
    4069         [ +  + ]:    33072784 :            rdiff(1:3)=rdiff_tmp(1:3)
    4070                 :             :          end if
    4071                 :             : 
    4072                 :             :        else
    4073                 :             :          ! Other lattices
    4074         [ +  + ]:     1803808 :          do ii=1,3
    4075                 :     1803808 :            rdiff(ii)=rcan(ii,ib)-rcan(ii,ia)+rpt(ii,irpt)
    4076                 :             :          end do
    4077                 :             :        end if
    4078                 :             : 
    4079                 :             :        ! Assignement of weights
    4080                 :             : 
    4081   [ +  +  +  + ]:     8896009 :        if(nqshft==1 .and. brav/=4)then
    4082                 :             : 
    4083         [ +  + ]:     8392758 :          if (brav/=1) then
    4084         [ +  + ]:      498248 :            do ii=1,3
    4085                 :             :              ! If the rpt vector is greater than the allowed space => weight = 0.0
    4086         [ +  + ]:      498248 :              if (abs(rdiff(ii))-tol10>factor*ngqpt(ii)) then
    4087                 :      182805 :                wghatm(ia,ib,irpt)=zero
    4088         [ +  + ]:      190881 :              else if (abs(abs(rdiff(ii))-factor*ngqpt(ii)) <=1.0d-10) then
    4089                 :             :                ! If the point is in a boundary position => weight/2
    4090                 :       36234 :                wghatm(ia,ib,irpt)=wghatm(ia,ib,irpt)/2
    4091                 :             :              end if
    4092                 :             :            end do
    4093                 :             :          else
    4094                 :             :            ! new weights
    4095                 :     8268196 :            wghatm(ia,ib,irpt)=zero
    4096                 :     8268196 :            nreq = 1
    4097         [ +  + ]:   344222748 :            do ii=1,nptws
    4098                 :   343774880 :              proj = rdiff(1)*ptws(1,ii)+rdiff(2)*ptws(2,ii)+rdiff(3)*ptws(3,ii)
    4099                 :             :              ! if rdiff closer to ptws than the origin the weight is zero
    4100                 :             :              ! if rdiff close to the origin with respect to all the other ptws the weight is 1
    4101                 :             :              ! if rdiff is equidistant from the origin and N other ptws the weight is 1/(N+1)
    4102         [ +  + ]:   344222748 :              if (proj - ptws(4,ii) > toldist) then
    4103                 :             :                nreq = 0
    4104                 :             :                EXIT
    4105         [ +  + ]:   335954552 :              else if(abs(proj-ptws(4,ii)) <= toldist) then
    4106                 :     1173541 :                nreq=nreq+1
    4107                 :             :              end if
    4108                 :             :            end do
    4109         [ +  + ]:     8268196 :            if (nreq>0) then
    4110                 :      447868 :              wghatm(ia,ib,irpt)=one/DBLE(nreq)
    4111                 :             :            end if
    4112                 :             :          end if
    4113                 :             : 
    4114         [ +  + ]:      500464 :        else if(brav==4)then
    4115                 :             :          ! Hexagonal
    4116                 :             :          ! Examination of the X and Y boundaries in order to form an hexagon
    4117                 :             :          ! First generate the relevant boundaries
    4118                 :      186446 :          rdiff(4)=0.5_dp*( rdiff(1)+sqrt(3.0_dp)*rdiff(2) )
    4119                 :      186446 :          ngqpt(4)=ngqpt(1)
    4120                 :      186446 :          rdiff(5)=0.5_dp*( rdiff(1)-sqrt(3.0_dp)*rdiff(2) )
    4121                 :      186446 :          ngqpt(5)=ngqpt(1)
    4122                 :             : 
    4123                 :             :          ! Test the four inequalities
    4124         [ +  + ]:     1118676 :          do ii=1,5
    4125         [ +  + ]:     1118676 :            if(ii/=2)then
    4126                 :             : 
    4127                 :      745784 :              nbord(ii)=0
    4128                 :             :              ! If the rpt vector is greater than the allowed space => weight = 0.0
    4129         [ +  + ]:      745784 :              if (abs(rdiff(ii))-1.0d-10>factor*ngqpt(ii)) then
    4130                 :      447478 :                wghatm(ia,ib,irpt)=zero
    4131         [ +  + ]:      298306 :              else if (abs(abs(rdiff(ii))-factor*ngqpt(ii)) <=1.0d-10) then
    4132                 :             :                ! If the point is in a boundary position increment nbord(ii)
    4133                 :       34204 :                nbord(ii)=1
    4134                 :             :              end if
    4135                 :             : 
    4136                 :             :            end if
    4137                 :             :          end do
    4138                 :             : 
    4139                 :             :          ! Computation of weights
    4140                 :      186446 :          nbordh=nbord(1)+nbord(4)+nbord(5)
    4141         [ +  + ]:      186446 :          if (nbordh==1) then
    4142                 :       20020 :            wghatm(ia,ib,irpt)=wghatm(ia,ib,irpt)/2
    4143         [ +  + ]:      166426 :          else if (nbordh==2) then
    4144                 :        2136 :            wghatm(ia,ib,irpt)=wghatm(ia,ib,irpt)/3
    4145         [ -  + ]:      164290 :          else if (nbordh/=0) then
    4146                 :           0 :            ABI_BUG('There is a problem of borders and weights (hex).')
    4147                 :             :          end if
    4148         [ +  + ]:      186446 :          if (nbord(3)==1)then
    4149                 :        9912 :            wghatm(ia,ib,irpt)=wghatm(ia,ib,irpt)/2
    4150                 :             :          end if
    4151                 :             : 
    4152         [ +  + ]:      314018 :        else if(nqshft==2 .and. brav/=4)then
    4153                 :             : 
    4154                 :             :          ! BCC packing of k-points
    4155                 :             :          ! First, generate the relevant boundaries
    4156                 :      221575 :          rdiff(4)= rdiff(1)+rdiff(2)
    4157                 :      221575 :          rdiff(5)= rdiff(1)-rdiff(2)
    4158                 :      221575 :          rdiff(6)= rdiff(1)+rdiff(3)
    4159                 :      221575 :          rdiff(7)= rdiff(1)-rdiff(3)
    4160                 :      221575 :          rdiff(8)= rdiff(3)+rdiff(2)
    4161                 :      221575 :          rdiff(9)= rdiff(3)-rdiff(2)
    4162   [ +  -  -  + ]:      221575 :          if(ngqpt(2)/=ngqpt(1) .or. ngqpt(3)/=ngqpt(1))then
    4163                 :             :            write(msg, '(a,a,a,3i6,a,a,a,a)' )&
    4164                 :           0 :            'In the BCC case, the three ngqpt numbers ',ch10,&
    4165                 :           0 :            '    ',ngqpt(1),ngqpt(2),ngqpt(3),ch10,&
    4166                 :           0 :            'should be equal.',ch10,&
    4167                 :           0 :            'Action: use identical ngqpt(1:3) in your input file.'
    4168                 :           0 :            ABI_ERROR(msg)
    4169                 :             :          end if
    4170         [ +  + ]:     1551025 :          do ii=4,9
    4171                 :     1551025 :            ngqpt(ii)=ngqpt(1)
    4172                 :             :          end do
    4173                 :             : 
    4174                 :             :          ! Test the relevant inequalities
    4175                 :      221575 :          nbord(1)=0
    4176         [ +  + ]:     1551025 :          do ii=4,9
    4177                 :             :            ! If the rpt vector is greater than the allowed space => weight = 0.0
    4178         [ +  + ]:     1551025 :            if (abs(rdiff(ii))-1.0d-10>factor*ngqpt(ii)) then
    4179                 :     1050176 :              wghatm(ia,ib,irpt)=zero
    4180         [ +  + ]:      279274 :            else if (abs(abs(rdiff(ii))-factor*ngqpt(ii)) <=1.0d-10) then
    4181                 :             :              ! If the point is in a boundary position increment nbord(1)
    4182                 :       86756 :              nbord(1)=nbord(1)+1
    4183                 :             :            end if
    4184                 :             :          end do
    4185                 :             : 
    4186                 :             :          ! Computation of weights
    4187         [ +  + ]:      221575 :          if (nbord(1)==1) then
    4188                 :       59196 :            wghatm(ia,ib,irpt)=wghatm(ia,ib,irpt)/2
    4189         [ +  + ]:      162379 :          else if (nbord(1)==2) then
    4190                 :       12268 :            wghatm(ia,ib,irpt)=wghatm(ia,ib,irpt)/3
    4191         [ +  + ]:      150111 :          else if (nbord(1)==3) then
    4192                 :         648 :            wghatm(ia,ib,irpt)=wghatm(ia,ib,irpt)/4
    4193         [ +  + ]:      149463 :          else if (nbord(1)==4) then
    4194                 :         270 :            wghatm(ia,ib,irpt)=wghatm(ia,ib,irpt)/6
    4195         [ -  + ]:      149193 :          else if (nbord(1)/=0) then
    4196                 :           0 :            ABI_ERROR(' There is a problem of borders and weights (BCC).')
    4197                 :             :          end if
    4198                 :             : 
    4199         [ +  - ]:       92443 :        else if(nqshft==4 .and. brav/=4)then
    4200                 :             : 
    4201                 :             :          ! FCC packing of k-points
    4202                 :             :          ! First, generate the relevant boundaries
    4203                 :       92443 :          rdiff(4)= (rdiff(1)+rdiff(2)+rdiff(3))*2._dp/3._dp
    4204                 :       92443 :          rdiff(5)= (rdiff(1)-rdiff(2)+rdiff(3))*2._dp/3._dp
    4205                 :       92443 :          rdiff(6)= (rdiff(1)+rdiff(2)-rdiff(3))*2._dp/3._dp
    4206                 :       92443 :          rdiff(7)= (rdiff(1)-rdiff(2)-rdiff(3))*2._dp/3._dp
    4207   [ +  -  -  + ]:       92443 :          if(ngqpt(2)/=ngqpt(1) .or. ngqpt(3)/=ngqpt(1))then
    4208                 :             :            write(msg, '(a,a,a,3i6,a,a,a,a)' )&
    4209                 :           0 :            'In the FCC case, the three ngqpt numbers ',ch10,&
    4210                 :           0 :            '    ',ngqpt(1),ngqpt(2),ngqpt(3),ch10,&
    4211                 :           0 :            'should be equal.',ch10,&
    4212                 :           0 :            'Action: use identical ngqpt(1:3) in your input file.'
    4213                 :           0 :            ABI_ERROR(msg)
    4214                 :             :          end if
    4215         [ +  + ]:      462215 :          do ii=4,7
    4216                 :      462215 :            ngqpt(ii)=ngqpt(1)
    4217                 :             :          end do
    4218                 :             : 
    4219                 :             :          ! Test the relevant inequalities
    4220                 :       92443 :          nbord(1)=0
    4221         [ +  + ]:      739544 :          do ii=1,7
    4222                 :             :            ! If the rpt vector is greater than the allowed space => weight = 0.0
    4223         [ +  + ]:      739544 :            if (abs(rdiff(ii))-1.0d-10>factor*ngqpt(ii)) then
    4224                 :      442496 :              wghatm(ia,ib,irpt)=zero
    4225                 :             :              ! If the point is in a boundary position increment nbord(1)
    4226         [ +  + ]:      204605 :            else if (abs(abs(rdiff(ii))-factor*ngqpt(ii)) <=1.0d-10) then
    4227                 :       44182 :              nbord(1)=nbord(1)+1
    4228                 :             :            end if
    4229                 :             :          end do
    4230                 :             : 
    4231                 :             :          ! Computation of weights
    4232         [ +  + ]:       92443 :          if (nbord(1)==1) then
    4233                 :       26290 :            wghatm(ia,ib,irpt)=wghatm(ia,ib,irpt)/2
    4234         [ +  + ]:       66153 :          else if (nbord(1)==2) then
    4235                 :        7590 :            wghatm(ia,ib,irpt)=wghatm(ia,ib,irpt)/3
    4236         [ +  + ]:       58563 :          else if (nbord(1)==3) then
    4237                 :         664 :            wghatm(ia,ib,irpt)=wghatm(ia,ib,irpt)/4
    4238   [ +  +  -  + ]:       57899 :          else if (nbord(1)/=0 .and. wghatm(ia,ib,irpt)>1.d-10) then
    4239                 :             :            ! Interestingly nbord(1)==4 happens for some points outside of the volume
    4240                 :           0 :            ABI_BUG(' There is a problem of borders and weights (FCC).')
    4241                 :             :          end if
    4242                 :             : 
    4243                 :             :        else
    4244                 :             :          write(msg, '(3a,i0,a)' )&
    4245                 :           0 :          'One should not arrive here ... ',ch10,&
    4246                 :           0 :          'The value nqshft ',nqshft,' is not available'
    4247                 :           0 :          ABI_BUG(msg)
    4248                 :             :        end if
    4249                 :             :      end do ! Assignement of weights is done
    4250                 :             :    end do ! End of the double loop on ia and ib
    4251                 :             :  end do
    4252                 :             : 
    4253                 :             :  ! Check the results
    4254         [ +  + ]:         892 :  do ia=1,natom
    4255         [ +  + ]:        3679 :    do ib=1,natom
    4256                 :             :      sumwght=zero
    4257         [ +  + ]:     8896009 :      do irpt=1,nrpt
    4258                 :             :        ! Check if the sum of the weights is equal to the number of q points
    4259                 :     8896009 :        sumwght=sumwght+wghatm(ia,ib,irpt)
    4260                 :             :        !write(std_out,'(a,3(i0,1x))' )' atom1, atom2, irpt ; rpt ; wghatm ',ia,ib,irpt
    4261                 :             :        !write(std_out,'(3es16.6,es18.6)' )rpt(1,irpt),rpt(2,irpt),rpt(3,irpt),wghatm(ia,ib,irpt)
    4262                 :             :      end do
    4263         [ +  + ]:        3434 :      if (abs(sumwght-nqpt)>tol10) ierr = 1
    4264                 :             :    end do
    4265                 :             :  end do
    4266                 :             : 
    4267                 :         245 : end subroutine wght9
    4268                 :             : !!***
    4269                 :             : 
    4270                 :             : !----------------------------------------------------------------------
    4271                 :             : 
    4272                 :             : !!****f* m_dynmat/d3sym
    4273                 :             : !! NAME
    4274                 :             : !! d3sym
    4275                 :             : !!
    4276                 :             : !! FUNCTION
    4277                 :             : !! Given a set of calculated elements of the 3DTE matrix,
    4278                 :             : !! build (nearly) all the other matrix elements that can be build using symmetries.
    4279                 :             : !!
    4280                 :             : !! INPUTS
    4281                 :             : !!  indsym(4,nsym,natom)=indirect indexing array : for each
    4282                 :             : !!   isym,iatom, fourth element is label of atom into which iatom is sent by
    4283                 :             : !!   INVERSE of symmetry operation isym; first three elements are the primitive
    4284                 :             : !!   translations which must be subtracted after the transformation to get back
    4285                 :             : !!   to the original unit cell.
    4286                 :             : !!  mpert =maximum number of ipert
    4287                 :             : !!  natom= number of atoms
    4288                 :             : !!  nsym=number of space group symmetries
    4289                 :             : !!  symrec(3,3,nsym)=3x3 matrices of the group symmetries (reciprocal space)
    4290                 :             : !!  symrel(3,3,nsym)=3x3 matrices of the group symmetries (real space)
    4291                 :             : !!
    4292                 :             : !! SIDE EFFECTS
    4293                 :             : !!  Input/Output
    4294                 :             : !!  blkflg(3,mpert,3,mpert,3,mpert)= matrix that indicates if an
    4295                 :             : !!   element of d3 is available (1 if available, 0 otherwise)
    4296                 :             : !!  d3(2,3,mpert,3,mpert,3,mpert)= matrix of the 3DTE
    4297                 :             : !!
    4298                 :             : !! SOURCE
    4299                 :             : 
    4300                 :          41 : subroutine d3sym(blkflg,d3,indsym,mpert,natom,nsym,symrec,symrel)
    4301                 :             : 
    4302                 :             : !Arguments -------------------------------
    4303                 :             : !scalars
    4304                 :             :  integer,intent(in) :: mpert,natom,nsym
    4305                 :             : !arrays
    4306                 :             :  integer,intent(in) :: indsym(4,nsym,natom),symrec(3,3,nsym),symrel(3,3,nsym)
    4307                 :             :  integer,intent(inout) :: blkflg(3,mpert,3,mpert,3,mpert)
    4308                 :             :  real(dp),intent(inout) :: d3(2,3,mpert,3,mpert,3,mpert)
    4309                 :             : 
    4310                 :             : !Local variables -------------------------
    4311                 :             : !scalars
    4312                 :             :  integer :: found,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert,idisy1,idisy2,idisy3
    4313                 :             :  integer :: ipesy1,ipesy2,ipesy3,isym,ithree
    4314                 :             :  real(dp) :: sumi,sumr
    4315                 :             : !arrays
    4316                 :             :  integer :: sym1(3,3),sym2(3,3),sym3(3,3)
    4317                 :             : ! *********************************************************************
    4318                 :             : 
    4319                 :             : !DEBUG
    4320                 :             : !write(std_out,*)'d3sym : enter'
    4321                 :             : !do i1dir = 1, 3
    4322                 :             : !do i2dir = 1, 3
    4323                 :             : !do i3dir = 1, 3
    4324                 :             : !write(std_out,*)i1dir,i2dir,i3dir,blkflg(i1dir,natom+2,i2dir,natom+2,i3dir,natom+2)
    4325                 :             : !end do
    4326                 :             : !end do
    4327                 :             : !end do
    4328                 :             : !stop
    4329                 :             : !ENDDEBUG
    4330                 :             : 
    4331                 :             : !First, take into account the permutations symmetry of
    4332                 :             : !(i1pert,i1dir) and (i3pert,i3dir)
    4333         [ +  + ]:         397 :  do i1pert = 1, mpert
    4334         [ +  + ]:        3665 :    do i2pert = 1, mpert
    4335         [ +  + ]:       36068 :      do i3pert = 1, mpert
    4336                 :             : 
    4337         [ +  + ]:      133044 :        do i1dir = 1, 3
    4338         [ +  + ]:      421772 :          do i2dir = 1, 3
    4339         [ +  + ]:     1265316 :            do i3dir = 1, 3
    4340                 :             : 
    4341   [ +  +  +  + ]:      875988 :              if ((blkflg(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)==1).and. &
    4342                 :      291996 : &             (blkflg(i3dir,i3pert,i2dir,i2pert,i1dir,i1pert)/=1)) then
    4343                 :             : 
    4344                 :             :                d3(:,i3dir,i3pert,i2dir,i2pert,i1dir,i1pert) = &
    4345         [ +  + ]:        3711 : &              d3(:,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)
    4346                 :             : 
    4347                 :        1237 :                blkflg(i3dir,i3pert,i2dir,i2pert,i1dir,i1pert) = 1
    4348                 :             : 
    4349                 :             :              end if
    4350                 :             : 
    4351                 :             :            end do
    4352                 :             :          end do
    4353                 :             :        end do
    4354                 :             : 
    4355                 :             :      end do
    4356                 :             :    end do
    4357                 :             :  end do
    4358                 :             : 
    4359                 :             : !Big Big Loop : symmetrize three times, because
    4360                 :             : !of some cases in which one element is not yet available
    4361                 :             : !at the first pass, and even at the second one !
    4362                 :             : 
    4363         [ +  + ]:         164 :  do ithree=1,3
    4364                 :             : 
    4365                 :             : !  Loop over perturbations
    4366         [ +  + ]:        1232 :    do i1pert = 1, mpert
    4367         [ +  + ]:       10995 :      do i2pert = 1, mpert
    4368         [ +  + ]:      108204 :        do i3pert = 1, mpert
    4369                 :             : 
    4370         [ +  + ]:      399132 :          do i1dir = 1, 3
    4371         [ +  + ]:     1265316 :            do i2dir = 1, 3
    4372         [ +  + ]:     3795948 :              do i3dir = 1, 3
    4373                 :             : 
    4374                 :             : !              Will get element (idir1,ipert1,idir2,ipert2)
    4375                 :             : !              so this element should not yet be present ...
    4376         [ +  + ]:     3503952 :                if(blkflg(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)/=1)then
    4377                 :             : 
    4378         [ +  + ]:     7831485 :                  d3(:,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert) = 0_dp
    4379                 :             : 
    4380         [ +  + ]:    47609064 :                  do isym = 1, nsym
    4381                 :             : 
    4382                 :    44998569 :                    found = 1
    4383                 :             : 
    4384         [ +  + ]:    44998569 :                    if (i1pert <= natom) then
    4385                 :     8178639 :                      ipesy1 = indsym(4,isym,i1pert)
    4386   [ +  +  +  + ]:   106322307 :                      sym1(:,:) = symrec(:,:,isym)
    4387         [ +  + ]:    36819930 :                    else if (i1pert == natom + 2) then
    4388                 :     3953370 :                      ipesy1 = i1pert
    4389   [ +  +  +  + ]:    51393810 :                      sym1(:,:) = symrel(:,:,isym)
    4390                 :             :                    else
    4391                 :             :                      found = 0
    4392                 :             :                    end if
    4393                 :             : 
    4394         [ +  + ]:    44998569 :                    if (i2pert <= natom) then
    4395                 :     8178639 :                      ipesy2 = indsym(4,isym,i2pert)
    4396   [ +  +  +  + ]:   106322307 :                      sym2(:,:) = symrec(:,:,isym)
    4397         [ +  + ]:    36819930 :                    else if (i2pert == natom + 2) then
    4398                 :     3953370 :                      ipesy2 = i2pert
    4399   [ +  +  +  + ]:    51393810 :                      sym2(:,:) = symrel(:,:,isym)
    4400                 :             :                    else
    4401                 :             :                      found = 0
    4402                 :             :                    end if
    4403                 :             : 
    4404         [ +  + ]:    44998569 :                    if (i3pert <= natom) then
    4405                 :     8178639 :                      ipesy3 = indsym(4,isym,i3pert)
    4406   [ +  +  +  + ]:   106322307 :                      sym3(:,:) = symrec(:,:,isym)
    4407         [ +  + ]:    36819930 :                    else if (i3pert == natom + 2) then
    4408                 :     3953370 :                      ipesy3 = i3pert
    4409   [ +  +  +  + ]:    51393810 :                      sym3(:,:) = symrel(:,:,isym)
    4410                 :             :                    else
    4411                 :             :                      found = 0
    4412                 :             :                    end if
    4413                 :             : 
    4414                 :    44998569 :                    sumr = 0_dp ; sumi = 0_dp;
    4415         [ +  + ]:   179994276 :                    do idisy1 = 1, 3
    4416         [ +  + ]:   584981397 :                      do idisy2 = 1, 3
    4417         [ +  + ]:  1754944191 :                        do idisy3 = 1, 3
    4418                 :             : 
    4419                 :             :                          if ((sym1(i1dir,idisy1) /=0).and.(sym2(i2dir,idisy2) /=0) &
    4420   [ +  +  +  +  :  1619948484 : &                         .and.(sym3(i3dir,idisy3) /=0)) then
                   +  + ]
    4421                 :             : 
    4422         [ +  + ]:   189920457 :                            if (blkflg(idisy1,ipesy1,idisy2,ipesy2,idisy3,ipesy3) == 1) then
    4423                 :             : 
    4424                 :             :                              sumr = sumr + sym1(i1dir,idisy1)*sym2(i2dir,idisy2)*&
    4425                 :   144869984 : &                             sym3(i3dir,idisy3)*d3(1,idisy1,ipesy1,idisy2,ipesy2,idisy3,ipesy3)
    4426                 :             :                              sumi = sumi + sym1(i1dir,idisy1)*sym2(i2dir,idisy2)*&
    4427                 :   144869984 : &                             sym3(i3dir,idisy3)*d3(2,idisy1,ipesy1,idisy2,ipesy2,idisy3,ipesy3)
    4428                 :             : 
    4429                 :             :                            else
    4430                 :             : 
    4431                 :             :                              found = 0
    4432                 :             : 
    4433                 :             :                            end if
    4434                 :             : 
    4435                 :             :                          end if
    4436                 :             : 
    4437                 :             :                        end do
    4438                 :             :                      end do
    4439                 :             :                    end do
    4440                 :             : 
    4441         [ +  + ]:    47609064 :                    if (found == 1) then
    4442                 :       18245 :                      d3(1,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert) = sumr
    4443                 :       18245 :                      d3(2,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert) = sumi
    4444                 :       18245 :                      blkflg(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert) = 1
    4445                 :             :                    end if
    4446                 :             : 
    4447                 :             :                  end do  ! isym
    4448                 :             : 
    4449                 :             :                end if  ! blkflg
    4450                 :             : 
    4451                 :             : !              Close loop over perturbations
    4452                 :             :              end do
    4453                 :             :            end do
    4454                 :             :          end do
    4455                 :             :        end do
    4456                 :             :      end do
    4457                 :             :    end do
    4458                 :             : 
    4459                 :             :  end do  ! close loop over ithree
    4460                 :             : 
    4461                 :          41 : end subroutine d3sym
    4462                 :             : !!***
    4463                 :             : 
    4464                 :             : !----------------------------------------------------------------------
    4465                 :             : 
    4466                 :             : !!****f* m_dynmat/sytens
    4467                 :             : !!
    4468                 :             : !! NAME
    4469                 :             : !! sytens
    4470                 :             : !!
    4471                 :             : !! FUNCTION
    4472                 :             : !! Determines the set of irreductible elements of the non-linear
    4473                 :             : !! optical susceptibility and Raman tensors
    4474                 :             : !!
    4475                 :             : !! INPUTS
    4476                 :             : !!  indsym(4,nsym,natom)=indirect indexing array described above: for each
    4477                 :             : !!   isym,iatom, fourth element is label of atom into which iatom is sent by
    4478                 :             : !!   INVERSE of symmetry operation isym; first three elements are the primitive
    4479                 :             : !!   translations which must be subtracted after the transformation to get back
    4480                 :             : !!   to the original unit cell.
    4481                 :             : !!  mpert =maximum number of ipert
    4482                 :             : !!  natom= number of atoms
    4483                 :             : !!  nsym=number of space group symmetries
    4484                 :             : !!  symrec(3,3,nsym)=3x3 matrices of the group symmetries (reciprocal space)
    4485                 :             : !!  symrel(3,3,nsym)=3x3 matrices of the group symmetries (real space)
    4486                 :             : !!
    4487                 :             : !! OUTPUT
    4488                 :             : !!  (see side effects)
    4489                 :             : !!
    4490                 :             : !! SIDE EFFECTS
    4491                 :             : !!  rfpert(3,mpert,3,mpert,3,mpert) = array defining the type of perturbations
    4492                 :             : !!       that have to be computed
    4493                 :             : !!    At the input :
    4494                 :             : !!       1   ->   element has to be computed explicitely
    4495                 :             : !!    At the output :
    4496                 :             : !!       1   ->   element has to be computed explicitely
    4497                 :             : !!      -1   ->   use symmetry operations to obtain the corresponding element
    4498                 :             : !!      -2   ->   element is zero by symmetry
    4499                 :             : !!
    4500                 :             : !! SOURCE
    4501                 :             : 
    4502                 :          46 : subroutine sytens(indsym,mpert,natom,nsym,rfpert,symrec,symrel)
    4503                 :             : 
    4504                 :             : !Arguments -------------------------------
    4505                 :             : !scalars
    4506                 :             :  integer,intent(in) :: mpert,natom,nsym
    4507                 :             : !arrays
    4508                 :             :  integer,intent(in) :: indsym(4,nsym,natom),symrec(3,3,nsym),symrel(3,3,nsym)
    4509                 :             :  integer,intent(inout) :: rfpert(3,mpert,3,mpert,3,mpert)
    4510                 :             : 
    4511                 :             : !Local variables -------------------------
    4512                 :             : !scalars
    4513                 :             :  integer :: flag,found,i1dir,i1dir_,i1pert,i1pert_,i2dir,i2dir_,i2pert,i2pert_
    4514                 :             :  integer :: i3dir,i3dir_,i3pert,i3pert_,idisy1,idisy2,idisy3,ipesy1,ipesy2
    4515                 :             :  integer :: ipesy3,isym
    4516                 :             : !arrays
    4517                 :             :  integer :: sym1(3,3),sym2(3,3),sym3(3,3)
    4518                 :          46 :  integer,allocatable :: pertsy(:,:,:,:,:,:)
    4519                 :             : !***********************************************************************
    4520                 :             : 
    4521   [ -  +  +  -  :         322 :  ABI_MALLOC(pertsy,(3,mpert,3,mpert,3,mpert))
          +  -  -  +  +  
          -  +  -  -  +  
          +  -  +  -  +  
             -  -  +  +  
                      - ]
    4522   [ +  +  +  +  :     1070750 :  pertsy(:,:,:,:,:,:) = 0
          +  +  +  +  +  
                +  +  + ]
    4523                 :             : 
    4524                 :             : !Loop over perturbations
    4525                 :             : 
    4526         [ +  + ]:         386 :  do i1pert_ = 1, mpert
    4527         [ +  + ]:        3302 :    do i2pert_ = 1, mpert
    4528         [ +  + ]:       31988 :      do i3pert_ = 1, mpert
    4529                 :             : 
    4530         [ +  + ]:      117844 :        do i1dir_ = 1, 3
    4531         [ +  + ]:      373516 :          do i2dir_ = 1, 3
    4532         [ +  + ]:     1120548 :            do i3dir_ = 1, 3
    4533                 :             : 
    4534                 :      775764 :              i1pert = (mpert - i1pert_ + 1)
    4535         [ +  + ]:      775764 :              if (i1pert <= natom) i1pert = natom + 1 - i1pert
    4536                 :      775764 :              i2pert = (mpert - i2pert_ + 1)
    4537         [ +  + ]:      775764 :              if (i2pert <= natom) i2pert = natom + 1 - i2pert
    4538                 :      775764 :              i3pert = (mpert - i3pert_ + 1)
    4539         [ +  + ]:      775764 :              if (i3pert <= natom) i3pert = natom + 1 - i3pert
    4540                 :             : 
    4541         [ +  + ]:      775764 :              if (i1pert <= natom) then
    4542                 :             :                i1dir = i1dir_ ; i2dir = i2dir_ ; i3dir = i3dir_
    4543         [ +  + ]:      618300 :              else if (i2pert <= natom) then
    4544                 :             :                i1dir = i2dir_ ; i2dir = i1dir_ ; i3dir = i3dir_
    4545         [ +  + ]:      497556 :              else if (i3pert <= natom) then
    4546                 :             :                i1dir = i3dir_ ; i2dir = i2dir_ ; i3dir = i1dir_
    4547                 :             :              else
    4548                 :      561060 :                i1dir = i1dir_ ; i2dir = i2dir_ ; i3dir = i3dir_
    4549                 :             :              end if
    4550                 :             : 
    4551         [ +  + ]:     1034352 :              if (rfpert(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert) /= 0) then
    4552                 :             : 
    4553                 :             : !              Loop over all symmetries
    4554                 :             : 
    4555                 :             :                flag = 0
    4556         [ +  + ]:      118983 :                do isym = 1, nsym
    4557                 :             : 
    4558                 :      113997 :                  found = 1
    4559                 :             : 
    4560                 :             : !                Select the symmetric element of i1pert,i2pert,i3pert
    4561                 :             : 
    4562         [ +  + ]:      113997 :                  if (i1pert <= natom) then
    4563                 :       31603 :                    ipesy1 = indsym(4,isym,i1pert)
    4564   [ +  +  +  + ]:      410839 :                    sym1(:,:) = symrec(:,:,isym)
    4565         [ +  - ]:       82394 :                  else if (i1pert == natom + 2) then
    4566                 :       82394 :                    ipesy1 = i1pert
    4567   [ +  +  +  + ]:     1071122 :                    sym1(:,:) = symrel(:,:,isym)
    4568                 :             :                  else
    4569                 :             :                    found = 0
    4570                 :             :                  end if
    4571                 :             : 
    4572         [ +  + ]:      113997 :                  if (i2pert <= natom) then
    4573                 :       31603 :                    ipesy2 = indsym(4,isym,i2pert)
    4574   [ +  +  +  + ]:      410839 :                    sym2(:,:) = symrec(:,:,isym)
    4575         [ +  - ]:       82394 :                  else if (i2pert == natom + 2) then
    4576                 :       82394 :                    ipesy2 = i2pert
    4577   [ +  +  +  + ]:     1071122 :                    sym2(:,:) = symrel(:,:,isym)
    4578                 :             :                  else
    4579                 :             :                    found = 0
    4580                 :             :                  end if
    4581                 :             : 
    4582         [ +  + ]:      113997 :                  if (i3pert <= natom) then
    4583                 :       31603 :                    ipesy3 = indsym(4,isym,i3pert)
    4584   [ +  +  +  + ]:      410839 :                    sym3(:,:) = symrec(:,:,isym)
    4585         [ +  - ]:       82394 :                  else if (i3pert == natom + 2) then
    4586                 :       82394 :                    ipesy3 = i3pert
    4587   [ +  +  +  + ]:     1071122 :                    sym3(:,:) = symrel(:,:,isym)
    4588                 :             :                  else
    4589                 :             :                    found = 0
    4590                 :             :                  end if
    4591                 :             : 
    4592                 :             : !                See if the symmetric element is available and check if some
    4593                 :             : !                of the elements may be zeor. In the latter case, they do not need
    4594                 :             : !                to be computed.
    4595                 :             : 
    4596                 :             : 
    4597                 :             :                  if ((flag /= -1).and.&
    4598   [ +  -  +  - ]:      113997 : &                 (ipesy1==i1pert).and.(ipesy2==i2pert).and.(ipesy3==i3pert)) then
    4599                 :      113997 :                    flag = sym1(i1dir,i1dir)*sym2(i2dir,i2dir)*sym3(i3dir,i3dir)
    4600                 :             :                  end if
    4601                 :             : 
    4602                 :             : 
    4603         [ +  + ]:      455988 :                  do idisy1 = 1, 3
    4604         [ +  + ]:     1481961 :                    do idisy2 = 1, 3
    4605         [ +  + ]:     4445883 :                      do idisy3 = 1, 3
    4606                 :             : 
    4607   [ +  +  +  +  :     3077919 :                        if ((sym1(i1dir,idisy1) /= 0).and.(sym2(i2dir,idisy2) /= 0).and.&
                   +  + ]
    4608                 :             : &                       (sym3(i3dir,idisy3) /= 0)) then
    4609         [ +  + ]:      394809 :                          if (pertsy(idisy1,ipesy1,idisy2,ipesy2,idisy3,ipesy3) == 0) then
    4610                 :     3077919 :                            found = 0
    4611                 :             : !                          exit      ! exit loop over symmetries
    4612                 :             :                          end if
    4613                 :             :                        end if
    4614                 :             : 
    4615                 :             : 
    4616   [ +  +  +  +  :     3077919 :                        if ((flag == -1).and.&
                   +  + ]
    4617                 :     1025973 : &                       ((idisy1/=i1dir).or.(idisy2/=i2dir).or.(idisy3/=i3dir))) then
    4618   [ +  +  +  +  :      127890 :                          if ((sym1(i1dir,idisy1)/=0).and.(sym2(i2dir,idisy2)/=0).and.&
                   +  + ]
    4619                 :             : &                         (sym3(i3dir,idisy3)/=0)) then
    4620                 :     3077919 :                            flag = 0
    4621                 :             :                          end if
    4622                 :             :                        end if
    4623                 :             : 
    4624                 :             :                      end do
    4625                 :             :                    end do
    4626                 :             :                  end do
    4627                 :             : 
    4628         [ +  + ]:      113997 :                  if (found == 1) then
    4629                 :       42006 :                    pertsy(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert) = -1
    4630                 :             :                  end if
    4631                 :             : 
    4632                 :             : !                In case a symmetry operation only changes the sign of an
    4633                 :             : !                element, this element has to be equal to zero
    4634                 :             : 
    4635         [ +  + ]:      118983 :                  if (flag == -1) then
    4636                 :        2228 :                    pertsy(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert) = -2
    4637                 :        2228 :                    exit
    4638                 :             :                  end if
    4639                 :             : 
    4640                 :             :                end do    ! close loop on symmetries
    4641                 :             : 
    4642                 :             : !              If the elemetn i1pert,i2pert,i3pert is not symmetric
    4643                 :             : !              to a basis element, it is a basis element
    4644                 :             : 
    4645         [ +  + ]:        7214 :                if (pertsy(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert) > -1) then
    4646                 :        2239 :                  pertsy(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert) = 1
    4647                 :             :                end if
    4648                 :             : 
    4649                 :             :              end if ! rfpert /= 0
    4650                 :             : 
    4651                 :             :            end do        ! close loop over perturbations
    4652                 :             :          end do
    4653                 :             :        end do
    4654                 :             :      end do
    4655                 :             :    end do
    4656                 :             :  end do
    4657                 :             : 
    4658                 :             : !Now, take into account the permutation of (i1pert,i1dir)
    4659                 :             : !and (i3pert,i3dir)
    4660                 :             : 
    4661         [ +  + ]:         386 :  do i1pert = 1, mpert
    4662         [ +  + ]:        3302 :    do i2pert = 1, mpert
    4663         [ +  + ]:       31988 :      do i3pert = 1, mpert
    4664                 :             : 
    4665         [ +  + ]:      117844 :        do i1dir = 1, 3
    4666         [ +  + ]:      373516 :          do i2dir = 1, 3
    4667         [ +  + ]:     1120548 :            do i3dir = 1, 3
    4668                 :             : 
    4669         [ +  + ]:     1034352 :              if ((i1pert /= i3pert).or.(i1dir /= i3dir)) then
    4670                 :             : 
    4671   [ +  +  +  + ]:      749520 :                if ((pertsy(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert) == 1).and.&
    4672                 :             : &               (pertsy(i3dir,i3pert,i2dir,i2pert,i1dir,i1pert) == 1)) then
    4673                 :         899 :                  pertsy(i3dir,i3pert,i2dir,i2pert,i1dir,i1pert) = -1
    4674                 :             :                end if
    4675                 :             : 
    4676                 :             :              end if
    4677                 :             : 
    4678                 :             :            end do
    4679                 :             :          end do
    4680                 :             :        end do
    4681                 :             : 
    4682                 :             :      end do
    4683                 :             :    end do
    4684                 :             :  end do
    4685                 :             : 
    4686   [ +  +  +  +  :     1070750 :  rfpert(:,:,:,:,:,:) = pertsy(:,:,:,:,:,:)
          +  +  +  +  +  
                +  +  + ]
    4687                 :             : 
    4688         [ -  + ]:          46 :  ABI_FREE(pertsy)
    4689                 :             : 
    4690                 :          46 : end subroutine sytens
    4691                 :             : !!***
    4692                 :             : 
    4693                 :             : 
    4694                 :             : !----------------------------------------------------------------------
    4695                 :             : 
    4696                 :             : !!****f* m_dynmat/axial9
    4697                 :             : !!
    4698                 :             : !! NAME
    4699                 :             : !! axial9
    4700                 :             : !!
    4701                 :             : !! FUNCTION
    4702                 :             : !! Generates the local coordinates system from the
    4703                 :             : !! knowledge of the first vector (longitudinal) and
    4704                 :             : !! the ifc matrix in cartesian coordinates
    4705                 :             : !!
    4706                 :             : !! INPUTS
    4707                 :             : !! ifccar(3,3)= matrix of interatomic force constants in cartesian coordinates
    4708                 :             : !! vect1(3)= cartesian coordinates of the first local vector
    4709                 :             : !!
    4710                 :             : !! OUTPUT
    4711                 :             : !! vect2(3)= cartesian coordinates of the second local vector
    4712                 :             : !! vect3(3)= cartesian coordinates of the third local vector
    4713                 :             : !!
    4714                 :             : !! SOURCE
    4715                 :             : 
    4716                 :       24995 : subroutine axial9(ifccar,vect1,vect2,vect3)
    4717                 :             : 
    4718                 :             : !Arguments -------------------------------
    4719                 :             : !arrays
    4720                 :             :  real(dp),intent(in) :: ifccar(3,3),vect1(3)
    4721                 :             :  real(dp),intent(out) :: vect2(3),vect3(3)
    4722                 :             : 
    4723                 :             : !Local variables -------------------------
    4724                 :             : !scalars
    4725                 :             :  integer :: flag,ii,itrial
    4726                 :             :  real(dp) :: innorm,scprod
    4727                 :             : !arrays
    4728                 :             :  real(dp) :: work(3)
    4729                 :             : ! *********************************************************************
    4730                 :             : 
    4731   [ +  +  +  + ]:      324935 :  work (:) = matmul(ifccar,vect1)
    4732                 :             : 
    4733                 :             :  flag=0
    4734         [ +  - ]:       63097 :  do itrial=1,4
    4735                 :             :    scprod=zero
    4736         [ +  + ]:      252388 :    do ii=1,3
    4737                 :      252388 :      scprod=scprod+work(ii)*vect1(ii)
    4738                 :             :    end do
    4739                 :             : 
    4740         [ +  + ]:      252388 :    work(:)=work(:)-vect1(:)*scprod
    4741                 :             : 
    4742         [ +  + ]:      252388 :    scprod=dot_product(work,work)
    4743                 :             : 
    4744         [ +  + ]:       63097 :    if(scprod<1.0d-10)then
    4745                 :       38102 :      work(1:3)=zero
    4746         [ +  + ]:       38102 :      if(itrial>1)work(itrial-1)=1.0_dp
    4747                 :             :    else
    4748                 :             :      flag=1
    4749                 :             :    end if
    4750                 :             : 
    4751                 :           0 :    if(flag==1)exit
    4752                 :             :  end do
    4753                 :             : 
    4754                 :       24995 :  innorm=scprod**(-0.5_dp)
    4755         [ +  + ]:       99980 :  vect2(:)=work(:)*innorm
    4756                 :             : 
    4757                 :       24995 :  vect3(1)=vect1(2)*vect2(3)-vect1(3)*vect2(2)
    4758                 :       24995 :  vect3(2)=vect1(3)*vect2(1)-vect1(1)*vect2(3)
    4759                 :       24995 :  vect3(3)=vect1(1)*vect2(2)-vect1(2)*vect2(1)
    4760                 :             : 
    4761                 :       24995 : end subroutine axial9
    4762                 :             : !!***
    4763                 :             : 
    4764                 :             : !----------------------------------------------------------------------
    4765                 :             : 
    4766                 :             : !!****f* m_dynmat/dymfz9
    4767                 :             : !!
    4768                 :             : !! NAME
    4769                 :             : !! dymfz9
    4770                 :             : !!
    4771                 :             : !! FUNCTION
    4772                 :             : !! As the subroutine canatm has transformed the coordinates of the
    4773                 :             : !! atoms in normalized canonical coordinates, the corresponding
    4774                 :             : !! dynamical matrix should be multiplied by a phase shift corresponding
    4775                 :             : !! to the translation between New and Old coordinates of its two
    4776                 :             : !! corresponding atoms.
    4777                 :             : !!
    4778                 :             : !! INPUTS
    4779                 :             : !! dynmat = non-phase shifted dynamical matrices
    4780                 :             : !! natom = number of atoms
    4781                 :             : !! nqpt = number of qpoints
    4782                 :             : !! gprim = reciprocal lattice vectors (cartesian but dimensionless)
    4783                 :             : !! option=1 : the matrices are transformed from the old (tn)
    4784                 :             : !!  coordinate system to the new (normalized canonical)
    4785                 :             : !!        2 : the matrices are restored from the normalized
    4786                 :             : !!  canonical coordinate system to the usual (tn) one...
    4787                 :             : !! rcan = canonical coordinates of atoms
    4788                 :             : !! spqpt = qpoint coordinates (reduced reciprocal)
    4789                 :             : !! trans = Atomic translations : xred = rcan + trans
    4790                 :             : !!
    4791                 :             : !! OUTPUT
    4792                 :             : !! dynmat = phase shifted dynamical matrices
    4793                 :             : !!
    4794                 :             : !! SOURCE
    4795                 :             : 
    4796                 :      697658 : subroutine dymfz9(dynmat,natom,nqpt,gprim,option,spqpt,trans)
    4797                 :             : 
    4798                 :             : !Arguments -------------------------------
    4799                 :             : !scalars
    4800                 :             :  integer,intent(in) :: natom,nqpt,option
    4801                 :             : !arrays
    4802                 :             :  real(dp),intent(in) :: gprim(3,3),spqpt(3,nqpt),trans(3,natom)
    4803                 :             :  real(dp),intent(inout) :: dynmat(2,3,natom,3,natom,nqpt)
    4804                 :             : 
    4805                 :             : !Local variables -------------------------
    4806                 :             : !scalars
    4807                 :             :  integer :: ia,ib,iqpt,mu,nu
    4808                 :             :  real(dp) :: im,ktrans,re
    4809                 :             : !arrays
    4810                 :             :  real(dp) :: kk(3)
    4811                 :             : ! *********************************************************************
    4812                 :             : 
    4813         [ +  + ]:     1421696 :  do iqpt=1,nqpt
    4814                 :             :    ! Definition of q in normalized reciprocal space
    4815   [ +  +  +  + ]:     9412494 :    kk(:) = matmul(gprim, spqpt(:, iqpt))
    4816                 :             : 
    4817                 :             : 
    4818         [ +  + ]:      724038 :    if(option==1)then
    4819         [ +  + ]:      106496 :      kk(:)=-kk(:)
    4820                 :             :    end if
    4821                 :             : 
    4822         [ +  + ]:     2706869 :    do ia=1,natom
    4823         [ +  + ]:     5163230 :      do ib=1,natom
    4824                 :             :        ! Product of q with the differences between the two atomic translations
    4825                 :     3154019 :        ktrans=kk(1)*(trans(1,ia)-trans(1,ib))+kk(2)*(trans(2,ia)-trans(2,ib))+kk(3)*(trans(3,ia)-trans(3,ib))
    4826         [ +  + ]:    13901249 :        do mu=1,3
    4827         [ +  + ]:    41002247 :          do nu=1,3
    4828                 :    28386171 :            re=dynmat(1,mu,ia,nu,ib,iqpt)
    4829                 :    28386171 :            im=dynmat(2,mu,ia,nu,ib,iqpt)
    4830                 :             :            ! Transformation of the Old dynamical matrices by New ones by multiplication by a phase shift
    4831                 :    28386171 :            dynmat(1,mu,ia,nu,ib,iqpt)=re*cos(two_pi*ktrans)-im*sin(two_pi*ktrans)
    4832                 :    37848228 :            dynmat(2,mu,ia,nu,ib,iqpt)=re*sin(two_pi*ktrans)+im*cos(two_pi*ktrans)
    4833                 :             :          end do
    4834                 :             :        end do
    4835                 :             :      end do
    4836                 :             :    end do
    4837                 :             :  end do
    4838                 :             : 
    4839                 :      697658 : end subroutine dymfz9
    4840                 :             : !!***
    4841                 :             : 
    4842                 :             : !----------------------------------------------------------------------
    4843                 :             : 
    4844                 :             : !!****f* m_dynmat/nanal9
    4845                 :             : !!
    4846                 :             : !! NAME
    4847                 :             : !! nanal9
    4848                 :             : !!
    4849                 :             : !! FUNCTION
    4850                 :             : !! If plus=0 then substracts the non-analytical part from one dynamical
    4851                 :             : !!           matrices, with number iqpt.
    4852                 :             : !! If plus=1 then adds the non-analytical part to the dynamical
    4853                 :             : !!           matrices, with number iqpt.
    4854                 :             : !!
    4855                 :             : !! For plus=0, see Eq.(76) in Gonze&Lee PRB 55, 10355 (1997) [[cite:Gonze1997a]],
    4856                 :             : !! get the left hand side.
    4857                 :             : !!
    4858                 :             : !! INPUTS
    4859                 :             : !! dyew(2,3,natom,3,natom)= Non-analytical part
    4860                 :             : !! natom= Number of atoms in the unit cell
    4861                 :             : !! iqpt= Referenced q point for the dynamical matrix
    4862                 :             : !! nqpt= Number of q points
    4863                 :             : !! plus= (see above)
    4864                 :             : !!
    4865                 :             : !! OUTPUT
    4866                 :             : !! dynmat(2,3,natom,3,natom,nqpt)= Dynamical matrices coming from the Derivative Data Base
    4867                 :             : !!
    4868                 :             : !! SOURCE
    4869                 :             : 
    4870                 :       74420 : subroutine nanal9(dyew,dynmat,iqpt,natom,nqpt,plus)
    4871                 :             : 
    4872                 :             : !Arguments -------------------------------
    4873                 :             : !scalars
    4874                 :             :  integer,intent(in) :: iqpt,natom,nqpt,plus
    4875                 :             : !arrays
    4876                 :             :  real(dp),intent(in) :: dyew(2,3,natom,3,natom)
    4877                 :             :  real(dp),intent(inout) :: dynmat(2,3,natom,3,natom,nqpt)
    4878                 :             : 
    4879                 :             : !Local variables -------------------------
    4880                 :             : !scalars
    4881                 :             :  integer :: ia,ib,mu,nu
    4882                 :             :  character(len=500) :: msg
    4883                 :             : ! *********************************************************************
    4884                 :             : 
    4885         [ +  + ]:       74420 :  if (plus==0) then
    4886                 :             : 
    4887         [ +  + ]:       49959 :    do ia=1,natom
    4888         [ +  + ]:      211388 :      do ib=1,natom
    4889         [ +  + ]:      684307 :        do mu=1,3
    4890         [ +  + ]:     2098577 :          do nu=1,3
    4891                 :             :            ! The following four lines are OK
    4892                 :     1452861 :            dynmat(1,mu,ia,nu,ib,iqpt)=dynmat(1,mu,ia,nu,ib,iqpt) - dyew(1,mu,ia,nu,ib)
    4893                 :     1937148 :            dynmat(2,mu,ia,nu,ib,iqpt)=dynmat(2,mu,ia,nu,ib,iqpt) - dyew(2,mu,ia,nu,ib)
    4894                 :             :          end do
    4895                 :             :        end do
    4896                 :             :      end do
    4897                 :             :    end do
    4898                 :             : 
    4899         [ +  - ]:       63052 :  else if (plus==1) then
    4900         [ +  + ]:      222768 :    do ia=1,natom
    4901         [ +  + ]:      791552 :      do ib=1,natom
    4902         [ +  + ]:     2434852 :        do mu=1,3
    4903         [ +  + ]:     7394192 :          do nu=1,3
    4904                 :     5119056 :            dynmat(1,mu,ia,nu,ib,iqpt)=dynmat(1,mu,ia,nu,ib,iqpt) + dyew(1,mu,ia,nu,ib)
    4905                 :     6825408 :            dynmat(2,mu,ia,nu,ib,iqpt)=dynmat(2,mu,ia,nu,ib,iqpt) + dyew(2,mu,ia,nu,ib)
    4906                 :             :          end do
    4907                 :             :        end do
    4908                 :             :      end do
    4909                 :             :    end do
    4910                 :             : 
    4911                 :             :  else
    4912                 :             :    write(msg,'(3a,i0,a)' )&
    4913                 :           0 :     'The argument "plus" must be equal to 0 or 1.',ch10,&
    4914                 :           0 :     'The value: ',plus,' is not available.'
    4915                 :           0 :    ABI_BUG(msg)
    4916                 :             :  end if
    4917                 :             : 
    4918                 :       74420 : end subroutine nanal9
    4919                 :             : !!***
    4920                 :             : 
    4921                 :             : !----------------------------------------------------------------------
    4922                 :             : 
    4923                 :             : !!****f* m_dynmat/gtdyn9
    4924                 :             : !!
    4925                 :             : !! NAME
    4926                 :             : !! gtdyn9
    4927                 :             : !!
    4928                 :             : !! FUNCTION
    4929                 :             : !! Generates a dynamical matrix from interatomic force
    4930                 :             : !! constants and long-range electrostatic interactions.
    4931                 :             : !!
    4932                 :             : !! INPUTS
    4933                 :             : !! acell(3)=length scales by which rprim is to be multiplied
    4934                 :             : !! atmfrc(3,natom,3,natom,nrpt) = Interatomic Forces in real space
    4935                 :             : !! dielt(3,3) = dielectric tensor
    4936                 :             : !! dipdip= if 0, no dipole-dipole interaction was subtracted in atmfrc
    4937                 :             : !!  if 1, atmfrc has been build without dipole-dipole part
    4938                 :             : !! dyewq0(3,3,natom)= Ewald part of the dynamical matrix, at q=0.
    4939                 :             : !! gmet(3,3)= metric tensor in reciprocal space.
    4940                 :             : !! gprim(3,3)= Normalized coordinates in reciprocal space
    4941                 :             : !! mpert =maximum number of ipert
    4942                 :             : !! natom= Number of atoms in the unit cell
    4943                 :             : !! nrpt= Number of R points in the Big Box
    4944                 :             : !! qphnrm= Normalisation coefficient for qpt
    4945                 :             : !! qpt(3)= Reduced coordinates of the q vectors in reciprocal space
    4946                 :             : !! rmet(3,3)= Metric tensor in real space.
    4947                 :             : !! rprim(3,3)= dimensionless primitive translations in real space
    4948                 :             : !! rpt(3,nprt)= Canonical coordinates of the R points in the unit cell
    4949                 :             : !!  These coordinates are normalized (=> * acell(3)!!)
    4950                 :             : !! trans(3,natom)= Atomic translations : xred = rcan + trans
    4951                 :             : !! ucvol= unit cell volume
    4952                 :             : !! wghatm(natom,natom,nrpt)= Weights associated to a pair of atoms and to a R vector
    4953                 :             : !! xred(3,natom)= relative coords of atoms in unit cell (dimensionless)
    4954                 :             : !! zeff(3,3,natom)=effective charge on each atom, versus electric field and atomic displacement
    4955                 :             : !! comm=MPI communicator.
    4956                 :             : !! [dipquad] = if 1, atmfrc has been build without dipole-quadrupole part
    4957                 :             : !! [quadquad] = if 1, atmfrc has been build without quadrupole-quadrupole part
    4958                 :             : !!
    4959                 :             : !! OUTPUT
    4960                 :             : !! d2cart(2,3,mpert,3,mpert)=dynamical matrix obtained for the wavevector qpt (normalized using qphnrm)
    4961                 :             : !! eta: parameter used to split R and G-space summation
    4962                 :             : !!
    4963                 :             : !! SOURCE
    4964                 :             : 
    4965                 :      229789 : subroutine gtdyn9(acell,atmfrc,dielt,dipdip,dyewq0,d2cart,gmet,gprim,mpert,natom,&
    4966                 :      229789 :                   nrpt,qphnrm,qpt,rmet,rprim,rpt,trans,ucvol,wghatm,xred,zeff,qdrp_cart,ewald_option,eta,comm,&
    4967                 :             :                   sys_dim,dipquad,quadquad,dielt_env,dielt_thick)  ! optional
    4968                 :             : 
    4969                 :             : !Arguments -------------------------------
    4970                 :             : !scalars
    4971                 :             :  integer,intent(in) :: dipdip,mpert,natom,nrpt,ewald_option,comm,sys_dim
    4972                 :             :  real(dp),intent(in) :: qphnrm,ucvol
    4973                 :             :  real(dp),optional,intent(in) :: dielt_env
    4974                 :             :  integer,optional,intent(in) :: dipquad, quadquad
    4975                 :             : !arrays
    4976                 :             :  real(dp), optional,intent(in):: dielt_thick(2)
    4977                 :             :  real(dp),intent(in) :: acell(3),dielt(3,3),gmet(3,3),gprim(3,3),qpt(3)
    4978                 :             :  real(dp),intent(in) :: rmet(3,3),rprim(3,3),rpt(3,nrpt)
    4979                 :             :  real(dp),intent(in) :: trans(3,natom),wghatm(natom,natom,nrpt),xred(3,natom)
    4980                 :             :  real(dp),intent(in) :: zeff(3,3,natom)
    4981                 :             :  real(dp),intent(in) :: qdrp_cart(3,3,3,natom)
    4982                 :             :  real(dp),intent(in) :: atmfrc(3,natom,3,natom,nrpt)
    4983                 :             :  real(dp),intent(in) :: dyewq0(3,3,natom)
    4984                 :             :  real(dp),intent(out) :: d2cart(2,3,mpert,3,mpert), eta
    4985                 :             : 
    4986                 :             : !Local variables -------------------------
    4987                 :             : !scalars
    4988                 :             :  integer,parameter :: nqpt1 = 1, option2 = 2, sumg0 = 0, plus1 = 1, iqpt1 = 1
    4989                 :             :  integer :: i1, i2, ib, nsize, dipquad_, quadquad_
    4990                 :             : !arrays
    4991                 :             :  real(dp) :: qphon(3) !, tsec(2)
    4992                 :      229789 :  real(dp),allocatable :: dq(:,:,:,:,:),dyew(:,:,:,:,:)
    4993                 :             : ! *********************************************************************
    4994                 :             : 
    4995                 :             :  ! Keep track of time spent in gtdyn9
    4996                 :             :  !call timab(1750, 1, tsec)
    4997                 :             : 
    4998   [ -  +  +  -  :     1148945 :  ABI_MALLOC(dq,(2,3,natom,3,natom))
          +  -  -  +  +  
          -  +  -  +  -  
             -  +  -  + ]
    4999                 :             : 
    5000                 :             :  ! Define quadrupolar options
    5001         [ +  + ]:      229789 :  dipquad_=0; if(present(dipquad)) dipquad_=dipquad
    5002         [ +  + ]:      229789 :  quadquad_=0; if(present(quadquad)) quadquad_=quadquad
    5003                 :             : 
    5004                 :             :  ! Get the normalized wavevector
    5005         [ +  + ]:      229789 :  if(abs(qphnrm)<1.0d-7)then
    5006                 :       18502 :    qphon(1:3)=zero
    5007                 :             :  else
    5008         [ +  + ]:      845148 :    qphon(1:3)=qpt(1:3)/qphnrm
    5009                 :             :  end if
    5010                 :             : 
    5011                 :             :  ! Generate the analytical part from the interatomic forces
    5012                 :      229789 :  call ftifc_r2q(atmfrc, dq, gprim, natom, nqpt1, nrpt, rpt, qphon, wghatm, comm)
    5013                 :             : 
    5014                 :             :  ! The analytical dynamical matrix dq has been generated
    5015                 :             :  ! in the normalized canonical coordinate system.
    5016                 :             :  ! Now, the phase is modified, in order to recover the usual (xred) coordinate of atoms.
    5017                 :      229789 :  call dymfz9(dq,natom,nqpt1,gprim,option2,qphon,trans)
    5018                 :             : 
    5019   [ +  +  +  + ]:      229789 :  if (dipdip==1.or.dipquad_==1.or.quadquad_==1) then
    5020                 :             :    ! Add the non-analytical part
    5021                 :             :    ! Compute dyew(2,3,natom,3,natom)= Ewald part of the dynamical matrix,
    5022                 :             :    ! second energy derivative wrt xred(3,natom) in Hartrees (Denoted A-bar in the notes)
    5023   [ -  +  +  -  :      189156 :    ABI_MALLOC(dyew,(2,3,natom,3,natom))
          -  +  +  -  -  
                +  -  + ]
    5024         [ +  + ]:       63052 :    if (sys_dim==1) then ! 3D case
    5025                 :             :      call ewald9(acell,dielt,dyew,gmet,gprim,natom,qphon,rmet,rprim,sumg0,ucvol,xred,zeff,&
    5026                 :       62830 :         qdrp_cart,eta,option=ewald_option,dipquad=dipquad_,quadquad=quadquad_)
    5027         [ +  - ]:         222 :    elseif (sys_dim<5) then
    5028                 :         222 :      call ewald9_2D(natom,acell,xred,rprim,dielt,dyew,qpt,zeff,qdrp_cart,dielt_env,dielt_thick,sys_dim)
    5029                 :             :    end if
    5030                 :             : 
    5031                 :       63052 :    call q0dy3_apply(natom,dyewq0,dyew)
    5032                 :       63052 :    call nanal9(dyew,dq,iqpt1,natom,nqpt1,plus1)
    5033                 :             : 
    5034         [ -  + ]:       63052 :    ABI_FREE(dyew)
    5035                 :             :  end if
    5036                 :             : 
    5037                 :             :  ! Copy the dynamical matrix in the proper location
    5038                 :             :  ! First zero all the elements
    5039                 :      229789 :  nsize=2*(3*mpert)**2
    5040   [ +  +  +  +  :   857018365 :  d2cart = zero
          +  +  +  +  +  
                      + ]
    5041                 :             : 
    5042                 :             :  ! Copy the elements from dq to d2cart
    5043   [ +  +  +  +  :    41294759 :  d2cart(:,:,1:natom,:,1:natom)=dq(:,:,1:natom,:,1:natom)
          +  +  +  +  +  
                      + ]
    5044                 :             : 
    5045                 :             :  ! In case we have the gamma point,
    5046         [ +  + ]:      229789 :  if(qphon(1)**2+qphon(2)**2+qphon(3)**2<1.d-14)then
    5047                 :             :    ! Copy the effective charge and dielectric constant in the final array
    5048         [ +  + ]:       77392 :    do i1=1,3
    5049         [ +  + ]:      251524 :      do i2=1,3
    5050                 :      174132 :        d2cart(1,i1,natom+2,i2,natom+2)=dielt(i1,i2)
    5051         [ +  + ]:      583140 :        do ib=1,natom
    5052                 :      350964 :          d2cart(1,i1,natom+2,i2,ib)=zeff(i1,i2,ib)
    5053                 :      525096 :          d2cart(1,i2,ib,i1,natom+2)=zeff(i1,i2,ib)
    5054                 :             :        end do
    5055                 :             :      end do
    5056                 :             :    end do
    5057                 :             :  end if
    5058                 :             : 
    5059         [ -  + ]:      229789 :  ABI_FREE(dq)
    5060                 :             : 
    5061                 :             :  !call timab(1750, 2, tsec)
    5062                 :             : 
    5063                 :      229789 : end subroutine gtdyn9
    5064                 :             : !!***
    5065                 :             : 
    5066                 :             : !----------------------------------------------------------------------
    5067                 :             : 
    5068                 :             : !!****f* m_dynmat/dfpt_phfrq
    5069                 :             : !! NAME
    5070                 :             : !! dfpt_phfrq
    5071                 :             : !!
    5072                 :             : !! FUNCTION
    5073                 :             : !! Get the phonon frequencies and eigenvectors (as well as the corresponding displacements)
    5074                 :             : !! If q is at Gamma, the non-analytical behaviour can be included.
    5075                 :             : !! Then, the effective dielectric tensor, the effective charges
    5076                 :             : !! and oscillator strengths for the limiting direction are also returned
    5077                 :             : !!
    5078                 :             : !! INPUTS
    5079                 :             : !!  amu(ntypat)=mass of the atoms (atomic mass unit) matrix (diagonal in the atoms)
    5080                 :             : !!  d2cart(2,3,mpert,3,mpert)=dynamical matrix, effective charges, dielectric tensor,.... all in cartesian coordinates
    5081                 :             : !!  indsym(4,msym*natom)=indirect indexing array : for each
    5082                 :             : !!   isym,iatom, fourth element is label of atom into which iatom is sent by
    5083                 :             : !!   INVERSE of symmetry operation isym; first three elements are the primitive
    5084                 :             : !!   translations which must be subtracted after the transformation to get back to the original unit cell.
    5085                 :             : !!  mpert =maximum number of ipert
    5086                 :             : !!  msym=maximum number of symmetries
    5087                 :             : !!  natom=number of atoms in unit cell
    5088                 :             : !!  nsym=number of space group symmetries
    5089                 :             : !!  ntypat=number of atom types
    5090                 :             : !!  qphnrm=(described above)
    5091                 :             : !!  qphon(3)= to be divided by qphnrm, give the phonon wavevector;
    5092                 :             : !!     if qphnrm==0.0_dp, then the wavevector is zero (Gamma point)
    5093                 :             : !!     and qphon gives the direction of the induced electric field in **CARTESIAN** coordinates.
    5094                 :             : !!     in the latter case, if qphon is zero, no non-analytical contribution is included.
    5095                 :             : !!  rprimd(3,3)=dimensional primitive translations (bohr)
    5096                 :             : !!  symdynmat=if 1, (re)symmetrize the dynamical matrix, except if Gamma wavevector with electric field added.
    5097                 :             : !!  symrel(3,3,nsym)=matrices of the group symmetries (real space)
    5098                 :             : !!  typat(natom)=integer label of each type of atom (1,2,...)
    5099                 :             : !!  ucvol=unit cell volume
    5100                 :             : !!
    5101                 :             : !! OUTPUT
    5102                 :             : !!  displ(2*3*natom*3*natom)= at the end, contains the displacements of atoms in cartesian coordinates.
    5103                 :             : !!    The first index means either the real or the imaginary part,
    5104                 :             : !!    The second index runs on the direction and the atoms displaced
    5105                 :             : !!    The third index runs on the modes.
    5106                 :             : !!  eigval(3*natom)=contains the eigenvalues of the dynamical matrix
    5107                 :             : !!  eigvec(2*3*natom*3*natom)= at the end, contains the eigenvectors of the dynamical matrix in cartesian coordinates.
    5108                 :             : !!  phfrq(3*natom)=phonon frequencies (square root of the dynamical matrix eigenvalues,
    5109                 :             : !!    except if these are negative, and in this case, give minus the square root of the absolute value
    5110                 :             : !!    of the matrix eigenvalues). Hartree units.
    5111                 :             : !!
    5112                 :             : !! NOTES
    5113                 :             : !!   1) One makes the dynamical matrix hermitian...
    5114                 :             : !!   2) In case of q=Gamma, only the real part is used.
    5115                 :             : !!      (MR: Modified since at finite omega imaginary components may arise
    5116                 :             : !!      also at Gamma in broken time-reversal symmetry crystals)
    5117                 :             : !!
    5118                 :             : !! SOURCE
    5119                 :             : 
    5120                 :      288112 : subroutine dfpt_phfrq(amu,displ,d2cart,eigval,eigvec,indsym,&
    5121                 :      288112 : & mpert,msym,natom,nsym,ntypat,phfrq,qphnrm,qphon,rprimd,&
    5122                 :      288112 : & symdynmat,symrel,symafm,typat,ucvol)
    5123                 :             : 
    5124                 :             : !Arguments -------------------------------
    5125                 :             : !scalars
    5126                 :             :  integer,intent(in) :: mpert,msym,natom,nsym,ntypat,symdynmat
    5127                 :             :  real(dp),intent(in) :: qphnrm,ucvol
    5128                 :             : !arrays
    5129                 :             :  integer,intent(in) :: indsym(4,msym*natom),symrel(3,3,nsym),typat(natom)
    5130                 :             :  integer,intent(in) :: symafm(nsym)
    5131                 :             :  real(dp),intent(in) :: amu(ntypat),d2cart(2,3,mpert,3,mpert),rprimd(3,3)
    5132                 :             :  real(dp),intent(inout) :: qphon(3)
    5133                 :             :  real(dp),intent(out) :: displ(2*3*natom*3*natom),eigval(3*natom)
    5134                 :             :  real(dp),intent(out) :: eigvec(2*3*natom*3*natom),phfrq(3*natom)
    5135                 :             : 
    5136                 :             : !Local variables -------------------------
    5137                 :             : !scalars
    5138                 :             :  integer :: analyt,i1,i2,idir1,idir2,ier,ii,imode,ipert1,ipert2
    5139                 :             :  integer :: jmode,indexi,indexj,index
    5140                 :             :  real(dp) :: epsq,qphon2
    5141                 :             :  logical,parameter :: debug = .False.
    5142                 :             :  real(dp) :: sc_prod
    5143                 :             : !arrays
    5144                 :             :  real(dp) :: qptn(3),dum(2,0) !, tsec(2)
    5145                 :      288112 :  real(dp),allocatable :: matrx(:,:),zeff(:,:),zhpev1(:,:),zhpev2(:)
    5146                 :             : ! *********************************************************************
    5147                 :             : 
    5148                 :             :  ! Keep track of time spent in dfpt_phfrq
    5149                 :             :  !call timab(1751, 1, tsec)
    5150                 :             : 
    5151                 :             :  ! GA: I find it strange that both msym and nsym are needed here.
    5152                 :             :  !     Moreover, there is an inconsistency in the dimensions of indsym
    5153                 :             :  !     when it is passed to symdyma.
    5154                 :             :  !     TODO: eliminate msym.
    5155                 :             : 
    5156                 :             :  ! Prepare the diagonalisation: analytical part.
    5157                 :             :  ! Note: displ is used as work space here
    5158                 :      288112 :  i1=0
    5159         [ +  + ]:      866371 :  do ipert1=1,natom
    5160         [ +  + ]:     2601148 :    do idir1=1,3
    5161                 :     1734777 :      i1=i1+1
    5162                 :     1734777 :      i2=0
    5163         [ +  + ]:     7092249 :      do ipert2=1,natom
    5164         [ +  + ]:    20851629 :        do idir2=1,3
    5165                 :    14337639 :          i2=i2+1
    5166                 :    14337639 :          index=i1+3*natom*(i2-1)
    5167                 :    14337639 :          displ(2*index-1)=d2cart(1,idir1,ipert1,idir2,ipert2)
    5168                 :    19116852 :          displ(2*index  )=d2cart(2,idir1,ipert1,idir2,ipert2)
    5169                 :             :        end do
    5170                 :             :      end do
    5171                 :             :    end do
    5172                 :             :  end do
    5173                 :             : 
    5174                 :             :  ! Determine the analyticity of the matrix.
    5175         [ +  + ]:      288112 :  analyt=1; if(abs(qphnrm)<tol8) analyt=0
    5176   [ +  +  +  +  :      288112 :  if(abs(qphon(1))<tol8.and.abs(qphon(2))<tol8.and.abs(qphon(3))<tol8) analyt=2
                   +  + ]
    5177                 :             : 
    5178                 :             :  ! In case of q=Gamma, only the real part is used
    5179         [ +  + ]:      288112 :  if(analyt==0 .or. analyt==2)then
    5180         [ +  + ]:      620081 :    do i1=1,3*natom
    5181         [ +  + ]:     4449464 :      do i2=1,3*natom
    5182                 :     3829383 :        index=i1+3*natom*(i2-1)
    5183         [ +  + ]:     4369674 :        if (abs(displ(2*index)) < tol14) displ(2*index)=zero
    5184                 :             :      end do
    5185                 :             :    end do
    5186                 :             :  end if
    5187                 :             : 
    5188                 :             :  ! In the case the non-analyticity is required:
    5189                 :             :  ! the tensor is in cartesian coordinates and this means that qphon must be in given in Cartesian coordinates.
    5190         [ +  + ]:       79790 :  if(analyt==0)then
    5191                 :             : 
    5192                 :             :    ! Normalize the limiting direction
    5193                 :       78727 :    qphon2=qphon(1)**2+qphon(2)**2+qphon(3)**2
    5194         [ +  + ]:      314908 :    qphon(:)=qphon(:)/sqrt(qphon2)
    5195                 :             : 
    5196                 :             :    ! Get the dielectric constant for the limiting direction
    5197                 :             :    epsq=zero
    5198         [ +  + ]:      314908 :    do idir1=1,3
    5199         [ +  + ]:     1023451 :      do idir2=1,3
    5200                 :      944724 :        epsq= epsq + qphon(idir1)*qphon(idir2) * d2cart(1,idir1,natom+2,idir2,natom+2)
    5201                 :             :      end do
    5202                 :             :    end do
    5203                 :             : 
    5204   [ -  +  +  -  :      236181 :    ABI_MALLOC(zeff,(3,natom))
          +  -  +  -  -  
                +  -  + ]
    5205                 :             : 
    5206                 :             :    ! Get the effective charges for the limiting direction
    5207         [ +  + ]:      314908 :    do idir1=1,3
    5208         [ +  + ]:      847738 :      do ipert1=1,natom
    5209                 :      532830 :        zeff(idir1,ipert1)=zero
    5210         [ +  + ]:     2367501 :        do idir2=1,3
    5211                 :     2131320 :          zeff(idir1,ipert1) = zeff(idir1,ipert1) + qphon(idir2)* d2cart(1,idir1,ipert1,idir2,natom+2)
    5212                 :             :        end do
    5213                 :             :      end do
    5214                 :             :    end do
    5215                 :             : 
    5216                 :             :    ! Get the non-analytical part of the dynamical matrix, and suppress its imaginary part.
    5217                 :             :    i1=0
    5218         [ +  + ]:      256337 :    do ipert1=1,natom
    5219         [ +  + ]:      789167 :      do idir1=1,3
    5220                 :      532830 :        i1=i1+1
    5221                 :      532830 :        i2=0
    5222         [ +  + ]:     1958770 :        do ipert2=1,natom
    5223         [ +  + ]:     5526150 :          do idir2=1,3
    5224                 :     3744990 :            i2=i2+1
    5225                 :     3744990 :            index=i1+3*natom*(i2-1)
    5226                 :     3744990 :            displ(2*index-1)=displ(2*index-1)+four_pi/ucvol*zeff(idir1,ipert1)*zeff(idir2,ipert2)/epsq
    5227         [ +  - ]:     4993320 :            if (abs(displ(2*index)) < tol14) displ(2*index)=zero
    5228                 :             :          end do
    5229                 :             :        end do
    5230                 :             :      end do
    5231                 :             :    end do
    5232                 :             : 
    5233         [ -  + ]:       78727 :    ABI_FREE(zeff)
    5234                 :             :  end if !  End of the non-analyticity treatment
    5235                 :             : 
    5236                 :             :  ! Multiply IFC(q) by masses
    5237                 :      288112 :  call massmult_and_breaksym(natom, ntypat, typat, amu, displ)
    5238                 :             :  ! ***********************************************************************
    5239                 :             :  ! Diagonalize the dynamical matrix
    5240                 :             : 
    5241                 :             :  !Symmetrize the dynamical matrix
    5242                 :             :  !FIXME: swap the next 2 lines and update test files to include symmetrization
    5243                 :             :  !       for Gamma point too (except in non-analytic case)
    5244                 :             :  !if (symdynmat==1 .and. analyt > 0) then
    5245   [ +  +  +  + ]:      288112 :  if (symdynmat==1 .and. analyt == 1) then
    5246                 :      202829 :    qptn(:)=qphon(:)
    5247         [ +  + ]:      811316 :    if (analyt==1) qptn(:)=qphon(:)/qphnrm
    5248                 :      202829 :    call symdyma(displ,indsym,natom,nsym,qptn,rprimd,symrel,symafm)
    5249                 :             :  end if
    5250                 :             : 
    5251                 :      288112 :  ii=1
    5252   [ +  -  -  +  :      864336 :  ABI_MALLOC(matrx,(2,(3*natom*(3*natom+1))/2))
          +  -  +  -  +  
             -  -  +  -  
                      + ]
    5253         [ +  + ]:     2022889 :  do i2=1,3*natom
    5254         [ +  + ]:    10059097 :    do i1=1,i2
    5255                 :     8036208 :      matrx(1,ii)=displ(1+2*(i1-1)+2*(i2-1)*3*natom)
    5256                 :     8036208 :      matrx(2,ii)=displ(2+2*(i1-1)+2*(i2-1)*3*natom)
    5257                 :     9770985 :      ii=ii+1
    5258                 :             :    end do
    5259                 :             :  end do
    5260                 :             : 
    5261   [ +  -  -  +  :      864336 :  ABI_MALLOC(zhpev1,(2,2*3*natom-1))
          +  -  +  -  +  
             -  -  +  -  
                      + ]
    5262   [ +  -  -  +  :      864336 :  ABI_MALLOC(zhpev2,(3*3*natom-2))
          +  -  +  -  +  
             -  -  +  -  
                      + ]
    5263                 :             : 
    5264                 :      288112 :  call ZHPEV ('V','U',3*natom,matrx,eigval,eigvec,3*natom,zhpev1,zhpev2,ier)
    5265         [ -  + ]:      288112 :  ABI_CHECK(ier == 0, sjoin('zhpev returned:', itoa(ier)))
    5266                 :             : 
    5267         [ -  + ]:      288112 :  ABI_FREE(matrx)
    5268         [ -  + ]:      288112 :  ABI_FREE(zhpev1)
    5269         [ -  + ]:      288112 :  ABI_FREE(zhpev2)
    5270                 :             : 
    5271                 :             :  if (debug) then
    5272                 :             :    ! Check the orthonormality of the eigenvectors
    5273                 :             :    do imode=1,3*natom
    5274                 :             :      do jmode=imode,3*natom
    5275                 :             :        indexi=2*3*natom*(imode-1)
    5276                 :             :        indexj=2*3*natom*(jmode-1)
    5277                 :             :        sc_prod=sum(eigvec(indexi+1:indexi+6*natom)*eigvec(indexj+1:indexj+6*natom))
    5278                 :             :        write(std_out,'(a,2i4,a,es16.6)')' imode,jmode=',imode,jmode,' real scalar product =',sc_prod
    5279                 :             :      end do
    5280                 :             :    end do
    5281                 :             :  end if
    5282                 :             :  !***********************************************************************
    5283                 :             : 
    5284                 :             :  ! Get the phonon frequencies (negative by convention, if the eigenvalue of the dynamical matrix is negative)
    5285         [ +  + ]:     2022889 :  do imode=1,3*natom
    5286         [ +  + ]:     2022889 :    if(eigval(imode)>=1.0d-16)then
    5287                 :     1517379 :      phfrq(imode)=sqrt(eigval(imode))
    5288         [ +  + ]:      217398 :    else if(eigval(imode)>=-1.0d-16)then
    5289                 :      158671 :      phfrq(imode)=zero
    5290                 :             :    else
    5291                 :       58727 :      phfrq(imode)=-sqrt(-eigval(imode))
    5292                 :             :    end if
    5293                 :             :  end do
    5294                 :             : 
    5295                 :             :  ! Fix the phase of the eigenvectors
    5296                 :      288112 :  call fxphas_seq(eigvec,dum, 0, 0, 1, 3*natom*3*natom, 0, 3*natom, 3*natom, 0)
    5297                 :             : 
    5298                 :             :  ! Normalise the eigenvectors
    5299                 :      288112 :  call pheigvec_normalize(natom, eigvec)
    5300                 :             : 
    5301                 :             :  ! Get the phonon displacements
    5302                 :      288112 :  call phdispl_from_eigvec(natom, ntypat, typat, amu, eigvec, displ)
    5303                 :             : 
    5304                 :             :  if (debug) then
    5305                 :             :    write(std_out,'(a)')' Phonon eigenvectors and displacements '
    5306                 :             :    do imode=1,3*natom
    5307                 :             :      indexi=2*3*natom*(imode-1)
    5308                 :             :      write(std_out,'(a,i4,a,12es16.6)')' imode=',imode,' eigvec(1:6*natom)=',eigvec(indexi+1:indexi+6*natom)
    5309                 :             :      write(std_out,'(a,i4,a,12es16.6)')' imode=',imode,' displ(1:6*natom)=',displ(indexi+1:indexi+6*natom)
    5310                 :             :    end do
    5311                 :             : 
    5312                 :             :    ! Check the orthonormality of the eigenvectors
    5313                 :             :    do imode=1,3*natom
    5314                 :             :      do jmode=imode,3*natom
    5315                 :             :        indexi=2*3*natom*(imode-1)
    5316                 :             :        indexj=2*3*natom*(jmode-1)
    5317                 :             :        sc_prod=sum(eigvec(indexi+1:indexi+6*natom)*eigvec(indexj+1:indexj+6*natom))
    5318                 :             :        write(std_out,'(a,2i4,a,es16.6)')' imode,jmode=',imode,jmode,' real scalar product =',sc_prod
    5319                 :             :      end do
    5320                 :             :    end do
    5321                 :             :  end if
    5322                 :             : 
    5323                 :             :  !call timab(1751, 2, tsec)
    5324                 :             : 
    5325                 :      288112 : end subroutine dfpt_phfrq
    5326                 :             : !!***
    5327                 :             : 
    5328                 :             : !----------------------------------------------------------------------
    5329                 :             : 
    5330                 :             : !!****f* m_dynmat/pheigvec_normalize
    5331                 :             : !!
    5332                 :             : !! NAME
    5333                 :             : !! pheigvec_normalize
    5334                 :             : !!
    5335                 :             : !! FUNCTION
    5336                 :             : !!  Normalize input eigenvectors in cartesian coordinates
    5337                 :             : !!
    5338                 :             : !! INPUTS
    5339                 :             : !!  natom: number of atoms in unit cell
    5340                 :             : !!
    5341                 :             : !! SIDE EFFECTS
    5342                 :             : !!  eigvec(2*3*natom*3*natom)=in output the normalized eigenvectors in cartesian coordinates.
    5343                 :             : !!
    5344                 :             : !! SOURCE
    5345                 :             : 
    5346                 :      288142 : pure subroutine pheigvec_normalize(natom, eigvec)
    5347                 :             : 
    5348                 :             : !Arguments -------------------------------
    5349                 :             : !scalars
    5350                 :             :  integer,intent(in) :: natom
    5351                 :             : !arrays
    5352                 :             :  real(dp),intent(inout) :: eigvec(2*3*natom*3*natom)
    5353                 :             : 
    5354                 :             : !Local variables -------------------------
    5355                 :             : !scalars
    5356                 :             :  integer :: i1,idir1,imode,ipert1,index
    5357                 :             :  real(dp) :: norm
    5358                 :             : ! *********************************************************************
    5359                 :             : 
    5360         [ +  + ]:     2023459 :  do imode=1,3*natom
    5361                 :             : 
    5362                 :             :    norm=zero
    5363         [ +  + ]:     6941268 :    do idir1=1,3
    5364         [ +  + ]:    21288627 :      do ipert1=1,natom
    5365                 :    14347359 :        i1=idir1+(ipert1-1)*3
    5366                 :    14347359 :        index=i1+3*natom*(imode-1)
    5367                 :    19553310 :        norm=norm+eigvec(2*index-1)**2+eigvec(2*index)**2
    5368                 :             :      end do
    5369                 :             :    end do
    5370                 :     1735317 :    norm=sqrt(norm)
    5371                 :             : 
    5372         [ +  + ]:     7229410 :    do idir1=1,3
    5373         [ +  + ]:    21288627 :      do ipert1=1,natom
    5374                 :    14347359 :        i1=idir1+(ipert1-1)*3
    5375                 :    14347359 :        index=i1+3*natom*(imode-1)
    5376                 :    14347359 :        eigvec(2*index-1)=eigvec(2*index-1)/norm
    5377                 :    19553310 :        eigvec(2*index)=eigvec(2*index)/norm
    5378                 :             :      end do
    5379                 :             :    end do
    5380                 :             : 
    5381                 :             :  end do
    5382                 :             : 
    5383                 :      288142 : end subroutine pheigvec_normalize
    5384                 :             : !!***
    5385                 :             : 
    5386                 :             : !----------------------------------------------------------------------
    5387                 :             : 
    5388                 :             : !!****f* m_dynmat/phdispl_from_eigvec
    5389                 :             : !! NAME
    5390                 :             : !! phdispl_from_eigvec
    5391                 :             : !!
    5392                 :             : !! FUNCTION
    5393                 :             : !!  Phonon displacements in cart coords from eigenvectors
    5394                 :             : !!
    5395                 :             : !! INPUTS
    5396                 :             : !!  natom: number of atoms in unit cell
    5397                 :             : !!  ntypat=number of atom types
    5398                 :             : !!  typat(natom)=integer label of each type of atom (1,2,...)
    5399                 :             : !!  amu(ntypat)=mass of the atoms (atomic mass unit) matrix (diagonal in the atoms)
    5400                 :             : !!  eigvec(2*3*natom*3*natom)= eigenvectors of the dynamical matrix in cartesian coordinates.
    5401                 :             : !!
    5402                 :             : !! OUTPUT
    5403                 :             : !!  displ(2*3*natom*3*natom)=displacements of atoms in cartesian coordinates.
    5404                 :             : !!
    5405                 :             : !! SOURCE
    5406                 :             : 
    5407                 :      294967 : pure subroutine phdispl_from_eigvec(natom, ntypat, typat, amu, eigvec, displ)
    5408                 :             : 
    5409                 :             : !Arguments -------------------------------
    5410                 :             : !scalars
    5411                 :             :  integer,intent(in) :: natom, ntypat
    5412                 :             : !arrays
    5413                 :             :  integer,intent(in) :: typat(natom)
    5414                 :             :  real(dp),intent(in) :: amu(ntypat)
    5415                 :             :  real(dp),intent(in) :: eigvec(2*3*natom*3*natom)
    5416                 :             :  real(dp),intent(out) :: displ(2*3*natom*3*natom)
    5417                 :             : 
    5418                 :             : !Local variables -------------------------
    5419                 :             : !scalars
    5420                 :             :  integer :: i1,idir1,imode,ipert1, index
    5421                 :             : ! *********************************************************************
    5422                 :             : 
    5423         [ +  + ]:     2068678 :  do imode=1,3*natom
    5424                 :             : 
    5425         [ +  + ]:     7389811 :    do idir1=1,3
    5426         [ +  + ]:    21664899 :      do ipert1=1,natom
    5427                 :    14570055 :        i1=idir1+(ipert1-1)*3
    5428                 :    14570055 :        index=i1+3*natom*(imode-1)
    5429                 :    14570055 :        displ(2*index-1)=eigvec(2*index-1) / sqrt(amu(typat(ipert1))*amu_emass)
    5430                 :    19891188 :        displ(2*index  )=eigvec(2*index  ) / sqrt(amu(typat(ipert1))*amu_emass)
    5431                 :             :      end do
    5432                 :             :    end do
    5433                 :             : 
    5434                 :             :  end do
    5435                 :             : 
    5436                 :      294967 : end subroutine phdispl_from_eigvec
    5437                 :             : !!***
    5438                 :             : 
    5439                 :             : !!****f* m_dynmat/phangmom_from_eigvec
    5440                 :             : !! NAME
    5441                 :             : !! phangmom_from_eigvec
    5442                 :             : !!
    5443                 :             : !! FUNCTION
    5444                 :             : !!  Phonon angular momenta in cart coords from eigenvectors
    5445                 :             : !!
    5446                 :             : !! INPUTS
    5447                 :             : !!  natom: number of atoms in unit cell
    5448                 :             : !!  eigvec(2*3*natom*3*natom)= eigenvectors of the dynamical matrix in cartesian coordinates.
    5449                 :             : !!
    5450                 :             : !! OUTPUT
    5451                 :             : !!  phangmom(3*3*natom)= angular momentum of each phonon mode in cartesian coordinates.
    5452                 :             : !!    The first index runs on the direction,
    5453                 :             : !!    The second index runs on the modes.
    5454                 :             : !!
    5455                 :             : !! SOURCE
    5456                 :             : 
    5457                 :        3178 : pure subroutine phangmom_from_eigvec(natom, eigvec, phangmom)
    5458                 :             : 
    5459                 :             : !Arguments -------------------------------
    5460                 :             : !scalars
    5461                 :             :  integer,intent(in) :: natom
    5462                 :             : !arrays
    5463                 :             :  real(dp),intent(in) :: eigvec(2*3*natom*3*natom)
    5464                 :             :  real(dp),intent(out) :: phangmom(3*3*natom)
    5465                 :             : 
    5466                 :             : !Local variables -------------------------
    5467                 :             : !scalars
    5468                 :             :  integer :: imode,ipert, index
    5469                 :             : !arrays
    5470                 :             :  real(dp) :: eigvecatom(2*3)
    5471                 :             : ! *********************************************************************
    5472                 :             : 
    5473         [ +  + ]:       75907 :  phangmom = zero
    5474                 :             : 
    5475         [ +  + ]:       27421 :  do imode=1,3*natom
    5476         [ +  + ]:      110704 :    do ipert=1,natom
    5477                 :       83283 :      index = 3*natom*(imode-1) + 3*(ipert-1)
    5478         [ +  + ]:      582981 :      eigvecatom = eigvec(2*index+1 : 2*index + 2*3) ! = Re(u_x), Im(u_x), Re(u_y), Im(u_y), Re(u_z), Im(u_z)
    5479                 :             :      phangmom(3*(imode-1)+1) = phangmom(3*(imode-1)+1)&
    5480                 :       83283 :              + two * (eigvecatom(3) * eigvecatom(6) - eigvecatom(4) * eigvecatom(5)) ! Re(u_y)*Im(u_z) - Im(u_y)*Re(u_z)
    5481                 :             :      phangmom(3*(imode-1)+2) = phangmom(3*(imode-1)+2)&
    5482                 :       83283 :              + two * (eigvecatom(5) * eigvecatom(2) - eigvecatom(6) * eigvecatom(1)) ! Re(u_z)*Im(u_x) - Im(u_z)*Re(u_x)
    5483                 :             :      phangmom(3*(imode-1)+3) = phangmom(3*(imode-1)+3)&
    5484                 :      107526 :              + two * (eigvecatom(1) * eigvecatom(4) - eigvecatom(2) * eigvecatom(3)) ! Re(u_x)*Im(u_y) - Im(u_x)*Re(u_y)
    5485                 :             :    end do
    5486                 :             :  end do
    5487                 :             : 
    5488                 :        3178 : end subroutine phangmom_from_eigvec
    5489                 :             : !!***
    5490                 :             : 
    5491                 :             : !!****f* m_dynmat/dfpt_prtph
    5492                 :             : !! NAME
    5493                 :             : !! dfpt_prtph
    5494                 :             : !!
    5495                 :             : !! FUNCTION
    5496                 :             : !! Print the phonon frequencies, on unit 6 as well as the printing
    5497                 :             : !! unit (except if the associated number -iout- is negative),
    5498                 :             : !! and for the latter, in Hartree, meV, Thz, Kelvin or cm-1.
    5499                 :             : !! If eivec==1,2, also print the eigenmodes : displacements in cartesian coordinates.
    5500                 :             : !! If eivec==4, generate output files for band2eps (drawing tool for the phonon band structure
    5501                 :             : !!
    5502                 :             : !! INPUTS
    5503                 :             : !!  displ(2,3*natom,3*natom)= contains the displacements of atoms in cartesian coordinates.
    5504                 :             : !!  The first index means either the real or the imaginary part,
    5505                 :             : !!  The second index runs on the direction and the atoms displaced
    5506                 :             : !!  The third index runs on the modes.
    5507                 :             : !!  eivec=(if eivec==0, the eigendisplacements are not printed,
    5508                 :             : !!    if eivec==1,2, the eigendisplacements are printed,
    5509                 :             : !!    if eivec==4, files for band2eps
    5510                 :             : !!  enunit=units for output of the phonon frequencies :
    5511                 :             : !!    0=> Hartree and cm-1, 1=> eV and Thz, other=> Ha,Thz,eV,cm-1 and K
    5512                 :             : !!  iout= unit for long print (if negative, the routine only print on unit 6, and in Hartree only).
    5513                 :             : !!  natom= number of atom
    5514                 :             : !!  phfrq(3*natom)= phonon frequencies in Hartree
    5515                 :             : !!  qphnrm=phonon wavevector normalisation factor
    5516                 :             : !!  qphon(3)=phonon wavevector
    5517                 :             : !!
    5518                 :             : !! OUTPUT
    5519                 :             : !!  Only printing
    5520                 :             : !!
    5521                 :             : !! NOTES
    5522                 :             : !! called by one processor only
    5523                 :             : !!
    5524                 :             : !! SOURCE
    5525                 :             : 
    5526                 :        1968 : subroutine dfpt_prtph(displ,eivec,enunit,iout,natom,phfrq,qphnrm,qphon)
    5527                 :             : 
    5528                 :             : !Arguments -------------------------------
    5529                 :             : !scalars
    5530                 :             :  integer,intent(in) :: eivec,enunit,iout,natom
    5531                 :             :  real(dp),intent(in) :: qphnrm
    5532                 :             : !arrays
    5533                 :             :  real(dp),intent(in) :: displ(2,3*natom,3*natom),phfrq(3*natom),qphon(3)
    5534                 :             : 
    5535                 :             : !Local variables -------------------------
    5536                 :             : !scalars
    5537                 :             :  integer :: i,idir,ii,imode,jj
    5538                 :             :  real(dp) :: tolerance
    5539                 :             :  logical :: t_degenerate
    5540                 :             :  character(len=500) :: msg
    5541                 :             : !arrays
    5542                 :             :  real(dp) :: vecti(3),vectr(3)
    5543                 :        3936 :  character(len=1) :: metacharacter(3*natom)
    5544                 :             : ! *********************************************************************
    5545                 :             : 
    5546                 :             : !Check the value of eivec
    5547   [ +  -  +  +  :        3830 :  if (all(eivec /= [0,1,2,4])) then
                   -  + ]
    5548                 :             :    write(msg, '(a,i0,a,a)' )&
    5549                 :           0 :    'In the calling subroutine, eivec is',eivec,ch10,&
    5550                 :           0 :    'but allowed values are between 0 and 4.'
    5551                 :           0 :    ABI_BUG(msg)
    5552                 :             :  end if
    5553                 :             : 
    5554                 :             : !write the phonon frequencies on unit std_out
    5555                 :        1968 :  write(msg,'(4a)' )' ',ch10,' phonon wavelength (reduced coordinates) , ','norm, and energies in hartree'
    5556                 :        1968 :  call wrtout(std_out,msg)
    5557                 :             : 
    5558                 :             : !The next format should be rewritten
    5559                 :        1968 :  write(msg,'(a,4f5.2)' )' ',(qphon(i),i=1,3),qphnrm
    5560                 :        1968 :  call wrtout(std_out,msg)
    5561   [ +  -  +  + ]:        6730 :  do jj=1,3*natom,5
    5562         [ +  + ]:        4762 :    if (3*natom-jj<5) then
    5563                 :        1968 :      write(msg,'(5es17.9)') (phfrq(ii),ii=jj,3*natom)
    5564                 :             :    else
    5565                 :        2794 :      write(msg,'(5es17.9)') (phfrq(ii),ii=jj,jj+4)
    5566                 :             :    end if
    5567                 :        6730 :    call wrtout(std_out,msg)
    5568                 :             :  end do
    5569         [ +  + ]:       20670 :  write(msg,'(a,a,es17.9)') ch10,' Zero Point Motion energy (sum of freqs/2)=',sum(phfrq(1:3*natom))/2
    5570                 :        1968 :  call wrtout(std_out,msg)
    5571                 :             : 
    5572                 :             : !Put the wavevector in nice format
    5573         [ +  + ]:        1968 :  if(iout>=0)then
    5574                 :        1932 :    call wrtout(iout,' ')
    5575         [ +  + ]:        1932 :    if(qphnrm/=0.0_dp)then
    5576                 :             :      write(msg, '(a,3f9.5)' )&
    5577   [ +  -  +  + ]:        6636 :      '  Phonon wavevector (reduced coordinates) :',(qphon(i)/qphnrm+tol10,i=1,3)
    5578                 :             :    else
    5579                 :             :      write(msg, '(3a,3f9.5)' )&
    5580                 :         273 :      '  Phonon at Gamma, with non-analyticity in the',ch10,&
    5581         [ +  + ]:        1365 :      '  direction (cartesian coordinates)',qphon(1:3)+tol10
    5582                 :             :    end if
    5583                 :        1932 :    call wrtout(iout,msg)
    5584                 :             : 
    5585                 :             : !  Write it, in different units.
    5586         [ +  - ]:        1932 :    if(enunit/=1)then
    5587                 :        1932 :      write(iout, '(a)' )' Phonon energies in Hartree :'
    5588   [ +  -  +  + ]:        6586 :      do jj=1,3*natom,5
    5589         [ +  + ]:        4654 :        if (3*natom-jj<5) then
    5590                 :        1932 :          write(msg, '(1x,5es14.6)') (phfrq(ii),ii=jj,3*natom)
    5591                 :             :        else
    5592                 :        2722 :          write(msg, '(1x,5es14.6)') (phfrq(ii),ii=jj,jj+4)
    5593                 :             :        end if
    5594                 :        6586 :        call wrtout(iout,msg)
    5595                 :             :      end do
    5596                 :             :    end if
    5597         [ +  + ]:        1932 :    if(enunit/=0)then
    5598                 :         158 :      write(iout, '(a)' )' Phonon energies in meV     :'
    5599   [ +  -  +  + ]:         388 :      do jj=1,3*natom,5
    5600         [ +  + ]:         230 :        if (3*natom-jj<5) then
    5601   [ +  -  +  + ]:         488 :          write(msg, '("-",5es14.6)') (phfrq(ii)*Ha_eV*1.0d3,ii=jj,3*natom)
    5602                 :             :        else
    5603   [ +  -  +  + ]:         432 :          write(msg, '("-",5es14.6)') (phfrq(ii)*Ha_eV*1.0d3,ii=jj,jj+4)
    5604                 :             :        end if
    5605                 :         388 :        call wrtout(iout,msg)
    5606                 :             :      end do
    5607                 :             :    end if
    5608         [ +  - ]:        1932 :    if(enunit/=1)then
    5609                 :        1932 :      write(iout, '(a)' )' Phonon frequencies in cm-1    :'
    5610   [ +  -  +  + ]:        6586 :      do jj=1,3*natom,5
    5611         [ +  + ]:        4654 :        if (3*natom-jj<5) then
    5612   [ +  -  +  + ]:        6580 :          write(msg, '("-",5es14.6)') (phfrq(ii)*Ha_cmm1,ii=jj,3*natom)
    5613                 :             :        else
    5614   [ +  -  +  + ]:       16332 :          write(msg, '("-",5es14.6)') (phfrq(ii)*Ha_cmm1,ii=jj,jj+4)
    5615                 :             :        end if
    5616                 :        6586 :        call wrtout(iout,msg)
    5617                 :             :      end do
    5618                 :             :    end if
    5619         [ +  + ]:        1932 :    if(enunit/=0)then
    5620                 :         158 :      write(iout, '(a)' )' Phonon frequencies in Thz     :'
    5621   [ +  -  +  + ]:         388 :      do jj=1,3*natom,5
    5622         [ +  + ]:         230 :        if (3*natom-jj<5) then
    5623   [ +  -  +  + ]:         488 :          write(msg, '("-",5es14.6)') (phfrq(ii)*Ha_THz,ii=jj,3*natom)
    5624                 :             :        else
    5625   [ +  -  +  + ]:         432 :          write(msg, '("-",5es14.6)') (phfrq(ii)*Ha_THz,ii=jj,jj+4)
    5626                 :             :        end if
    5627                 :         388 :        call wrtout(iout,msg)
    5628                 :             :      end do
    5629                 :             :    end if
    5630         [ +  + ]:        1932 :    if(enunit/=0.and.enunit/=1)then
    5631                 :         158 :      write(iout, '(a)' )' Phonon energies in Kelvin  :'
    5632   [ +  -  +  + ]:         388 :      do jj=1,3*natom,5
    5633         [ +  + ]:         230 :        if (3*natom-jj<5) then
    5634   [ +  -  +  + ]:         488 :          write(msg, '("-",5es14.6)') (phfrq(ii)/kb_HaK,ii=jj,3*natom)
    5635                 :             :        else
    5636   [ +  -  +  + ]:         432 :          write(msg, '("-",5es14.6)') (phfrq(ii)/kb_HaK,ii=jj,jj+4)
    5637                 :             :        end if
    5638                 :         388 :        call wrtout(iout,msg)
    5639                 :             :      end do
    5640                 :             :    end if
    5641                 :             :  end if
    5642                 :             : 
    5643                 :             : !Take care of the eigendisplacements
    5644         [ +  + ]:        1968 :  if(eivec==1 .or. eivec==2)then
    5645                 :          83 :    write(msg, '(a,a,a,a,a,a,a,a)' ) ch10,&
    5646                 :          83 :    ' Eigendisplacements ',ch10,&
    5647                 :          83 :    ' (will be given, for each mode : in cartesian coordinates',ch10,&
    5648                 :          83 :    '   for each atom the real part of the displacement vector,',ch10,&
    5649                 :         166 :    '   then the imaginary part of the displacement vector - absolute values smaller than 1.0d-7 are set to zero)'
    5650                 :          83 :    call wrtout(std_out,msg)
    5651         [ +  - ]:          83 :    if(iout>=0) then
    5652                 :          83 :      call wrtout(iout,msg)
    5653                 :             :    end if
    5654                 :             : 
    5655                 :             : !  Examine the degeneracy of each mode. The portability of the echo of the eigendisplacements
    5656                 :             : !  is very hard to obtain, and has not been attempted.
    5657         [ +  + ]:         452 :    do imode=1,3*natom
    5658                 :             : !    The degenerate modes are not portable
    5659                 :         369 :      t_degenerate=.false.
    5660         [ +  + ]:         369 :      if(imode>1)then
    5661         [ +  + ]:         286 :        if(phfrq(imode)-phfrq(imode-1)<tol6)t_degenerate=.true.
    5662                 :             :      end if
    5663         [ +  + ]:         369 :      if(imode<3*natom)then
    5664         [ +  + ]:         286 :        if(phfrq(imode+1)-phfrq(imode)<tol6)t_degenerate=.true.
    5665                 :             :      end if
    5666         [ +  + ]:         452 :      metacharacter(imode)=';'; if(t_degenerate)metacharacter(imode)='-'
    5667                 :             :    end do
    5668                 :             : 
    5669         [ +  + ]:         452 :    do imode=1,3*natom
    5670                 :         369 :      write(msg,'(a,i4,a,es16.6)' )'  Mode number ',imode,'   Energy',phfrq(imode)
    5671                 :         369 :      call wrtout(std_out,msg)
    5672         [ +  - ]:         369 :      if(iout>=0)then
    5673                 :         369 :        write(msg, '(a,i4,a,es16.6)' )'  Mode number ',imode,'   Energy',phfrq(imode)
    5674                 :         369 :        call wrtout(iout,msg)
    5675                 :             :      end if
    5676                 :         369 :      tolerance=1.0d-7
    5677         [ +  + ]:         369 :      if(abs(phfrq(imode))<1.0d-5)tolerance=2.0d-7
    5678         [ +  + ]:         369 :      if(phfrq(imode)<1.0d-5)then
    5679                 :         202 :        write(msg,'(3a)' )' Attention : low frequency mode.',ch10,&
    5680                 :         404 :        '   (Could be unstable or acoustic mode)'
    5681                 :         202 :        call wrtout(std_out,msg)
    5682         [ +  - ]:         202 :        if(iout>=0)then
    5683                 :         202 :          write(iout, '(3a)' )' Attention : low frequency mode.',ch10,&
    5684                 :         404 :          '   (Could be unstable or acoustic mode)'
    5685                 :             :        end if
    5686                 :             :      end if
    5687         [ +  + ]:        1277 :      do ii=1,natom
    5688         [ +  + ]:        3300 :        do idir=1,3
    5689                 :        2475 :          vectr(idir)=displ(1,idir+(ii-1)*3,imode)
    5690         [ +  + ]:        2475 :          if(abs(vectr(idir))<tolerance)vectr(idir)=0.0_dp
    5691                 :        2475 :          vecti(idir)=displ(2,idir+(ii-1)*3,imode)
    5692         [ +  - ]:        3300 :          if(abs(vecti(idir))<tolerance)vecti(idir)=0.0_dp
    5693                 :             :        end do
    5694                 :         825 :        write(msg,'(i4,3es16.8,a,4x,3es16.8)' ) ii,vectr(:),ch10,vecti(:)
    5695                 :         825 :        call wrtout(std_out,msg)
    5696         [ +  - ]:        1194 :        if(iout>=0)then
    5697                 :         825 :          write(msg,'(a,i3,3es16.8,2a,3x,3es16.8)') metacharacter(imode),ii,vectr(:),ch10,&
    5698                 :        1650 :            metacharacter(imode), vecti(:)
    5699                 :         825 :          call wrtout(iout,msg)
    5700                 :             :        end if
    5701                 :             :      end do
    5702                 :             :    end do
    5703                 :             :  end if
    5704                 :             : 
    5705                 :        1968 : end subroutine dfpt_prtph
    5706                 :             : !!***
    5707                 :             : 
    5708                 :             : !!****f* m_dynmat/massmult_and_breaksym
    5709                 :             : !! NAME
    5710                 :             : !!  mult_masses_and_break_symms
    5711                 :             : !!
    5712                 :             : !! FUNCTION
    5713                 :             : !!  Multiply the IFC(q) by the atomic masses, slightly break symmetry to make tests more
    5714                 :             : !!  portable and make the matrix hermitian before returning.
    5715                 :             : !!
    5716                 :             : !! INPUTS
    5717                 :             : !!  amu(ntypat)=mass of the atoms (atomic mass unit) matrix (diagonal in the atoms)
    5718                 :             : !!  natom=number of atoms in unit cell
    5719                 :             : !!  ntypat=number of atom types
    5720                 :             : !!  typat(natom)=integer label of each type of atom (1,2,...)
    5721                 :             : !!  [herm_opt]= 1 to hermitianize mat (default)
    5722                 :             : !!              0 if no symmetrization should be performed
    5723                 :             : !!
    5724                 :             : !! SIDE EFFECTS
    5725                 :             : !!  mat(2*3*natom*3*natom)=Multiplies by atomic masses in output.
    5726                 :             : !!
    5727                 :             : !! SOURCE
    5728                 :             : 
    5729                 :      756421 : subroutine massmult_and_breaksym(natom, ntypat, typat, amu, mat, &
    5730                 :             :                                  herm_opt) ! optional
    5731                 :             : 
    5732                 :             : !Arguments -------------------------------
    5733                 :             : !scalars
    5734                 :             :  integer,intent(in) :: natom,ntypat
    5735                 :             :  integer,optional,intent(in) :: herm_opt
    5736                 :             : !arrays
    5737                 :             :  integer,intent(in) :: typat(natom)
    5738                 :             :  real(dp),intent(in) :: amu(ntypat)
    5739                 :             :  real(dp),intent(inout) :: mat(2*3*natom*3*natom)
    5740                 :             : 
    5741                 :             : !Local variables -------------------------
    5742                 :             : !scalars
    5743                 :             :  integer :: i1,i2,idir1,idir2,index,ipert1,ipert2, herm_opt__
    5744                 :             :  real(dp),parameter :: break_symm=1.0d-12
    5745                 :             :  !real(dp),parameter :: break_symm=zero
    5746                 :             :  real(dp) :: fac
    5747                 :             : !arrays
    5748                 :             :  real(dp) :: nearidentity(3,3)
    5749                 :             : ! *********************************************************************
    5750                 :             : 
    5751         [ -  + ]:      756421 :  herm_opt__ = 1; if (present(herm_opt)) herm_opt__ = herm_opt
    5752                 :             : 
    5753                 :             :  ! This slight breaking of the symmetry allows the results to be more portable between machines
    5754   [ +  +  +  + ]:     9833473 :  nearidentity(:,:)=one
    5755                 :      756421 :  nearidentity(1,1)=one+break_symm
    5756                 :      756421 :  nearidentity(3,3)=one-break_symm
    5757                 :             : 
    5758                 :             :  ! Include the masses in the dynamical matrix
    5759         [ +  + ]:     2096071 :  do ipert1=1,natom
    5760         [ +  + ]:     5132181 :    do ipert2=1,natom
    5761                 :     3036110 :      fac=1.0_dp/sqrt(amu(typat(ipert1))*amu(typat(ipert2)))/amu_emass
    5762         [ +  + ]:    13484090 :      do idir1=1,3
    5763         [ +  + ]:    39469430 :        do idir2=1,3
    5764                 :    27324990 :          i1=idir1+(ipert1-1)*3
    5765                 :    27324990 :          i2=idir2+(ipert2-1)*3
    5766                 :    27324990 :          index=i1+3*natom*(i2-1)
    5767                 :    27324990 :          mat(2*index-1)=mat(2*index-1)*fac*nearidentity(idir1,idir2)
    5768                 :    27324990 :          mat(2*index  )=mat(2*index  )*fac*nearidentity(idir1,idir2)
    5769                 :             :          ! This is to break slightly the translation invariance, and make the automatic tests more portable
    5770         [ +  + ]:    36433320 :          if(ipert1==ipert2 .and. idir1==idir2)then
    5771                 :     4018950 :            mat(2*index-1)=mat(2*index-1)+break_symm*natom/amu_emass/idir1*0.01_dp
    5772                 :             :          end if
    5773                 :             :        end do
    5774                 :             :      end do
    5775                 :             :    end do
    5776                 :             :  end do
    5777                 :             : 
    5778                 :             :  ! Make the dynamical matrix hermitian
    5779         [ +  - ]:      756421 :  if (herm_opt__ == 1) call mkherm(mat,3*natom)
    5780                 :             : 
    5781                 :      756421 : end subroutine massmult_and_breaksym
    5782                 :             : !!***
    5783                 :             : 
    5784                 :             : !!****f* m_dynmat/massmult_and_breaksym_cplx
    5785                 :             : !! NAME
    5786                 :             : !!  mult_masses_and_break_symms_cplx
    5787                 :             : !!
    5788                 :             : !! FUNCTION
    5789                 :             : !!  Similar to massmult_and_breaksym, the only difference is that it receives complex array.
    5790                 :             : 
    5791                 :           0 : subroutine massmult_and_breaksym_cplx(natom, ntypat, typat, amu, cmat, &
    5792                 :             :                                       herm_opt) ! optional
    5793                 :             : 
    5794                 :             : !Arguments -------------------------------
    5795                 :             : !scalars
    5796                 :             :  integer,intent(in) :: natom,ntypat
    5797                 :             :  integer,optional,intent(in) :: herm_opt
    5798                 :             : !arrays
    5799                 :             :  integer,intent(in) :: typat(natom)
    5800                 :             :  real(dp),intent(in) :: amu(ntypat)
    5801                 :             :  complex(dp),target,intent(inout) :: cmat(2*3*natom*3*natom)
    5802                 :             : 
    5803                 :             : !Local variables -------------------------
    5804                 :             :  integer :: herm_opt__
    5805                 :             :  real(dp),pointer :: rmat_ptr(:)
    5806                 :             : ! *************************************************************************
    5807                 :             : 
    5808         [ #  # ]:           0 :  call C_F_pointer(c_loc(cmat), rmat_ptr, shape=[3*natom*3*natom])
    5809         [ #  # ]:           0 :  herm_opt__ = 1; if (present(herm_opt)) herm_opt__ = herm_opt
    5810         [ #  # ]:           0 :  call massmult_and_breaksym(natom, ntypat, typat, amu, rmat_ptr, herm_opt=herm_opt__)
    5811                 :             : 
    5812                 :           0 : end subroutine massmult_and_breaksym_cplx
    5813                 :             : !!***
    5814                 :             : 
    5815                 :             : !!****f* m_dynmat/ftgam
    5816                 :             : !! NAME
    5817                 :             : !! ftgam
    5818                 :             : !!
    5819                 :             : !! FUNCTION
    5820                 :             : !! If qtor=1 (q->r):
    5821                 :             : !!  Generates the Fourier transform of the recip space gkk matrices
    5822                 :             : !!  to obtain the real space ones.
    5823                 :             : !! If qtor=0 (r->q):
    5824                 :             : !!  Generates the Fourier transform of the real space gkk matrices
    5825                 :             : !!  to obtain the reciprocal space ones.
    5826                 :             : !!
    5827                 :             : !! INPUTS
    5828                 :             : !! natom= Number of atoms in the unit cell
    5829                 :             : !! nqpt= Number of q points in the Brillouin zone
    5830                 :             : !!           if qtor=0 this number is read in the input file
    5831                 :             : !! nrpt= Number of R points in the Big Box
    5832                 :             : !! qtor= ( q to r : see above )
    5833                 :             : !! rpt(3,nprt)= Canonical coordinates of the R points in the unit cell
    5834                 :             : !!           These coordinates are normalized (=> * acell(3)!!)
    5835                 :             : !! qpt_full(3,nqpt)= Reduced coordinates of the q vectors in reciprocal space
    5836                 :             : !!           if qtor=0 these vectors are read in the input file
    5837                 :             : !! wghatm(natom,natom,nrpt)= Weights associated to a pair of atoms and to a R vector
    5838                 :             : !!
    5839                 :             : !! OUTPUT
    5840                 :             : !!  (see side effects)
    5841                 :             : !!
    5842                 :             : !! SIDE EFFECTS
    5843                 :             : !! Input/output
    5844                 :             : !! gam_qpt(2,3*natom*3*natom,nqpt)
    5845                 :             : !!  = gamma matrices in recip space coming from the Derivative Data Base
    5846                 :             : !! gam_rpt(2,3*natom*3*natom,nrpt)
    5847                 :             : !!  = gamma matrices in real space stored in file unit_gkk_rpt
    5848                 :             : !!
    5849                 :             : !! NOTES
    5850                 :             : !!   copied from ftiaf9.f
    5851                 :             : !!   recip to real space: real space is forced to disk file unit_gkk_rpt
    5852                 :             : !!                        recip space depends on gkqwrite and unitgkq3
    5853                 :             : !!   real to recip space: real space is forced to disk file unit_gkk_rpt
    5854                 :             : !!                        recip space is necessarily in memory in gkk_qpt
    5855                 :             : !!
    5856                 :             : !!    real space elements are complex, but could be reduced, as (-r) = (+r)*
    5857                 :             : !!
    5858                 :             : !! SOURCE
    5859                 :             : 
    5860                 :       26898 : subroutine ftgam (wghatm,gam_qpt,gam_rpt,natom,nqpt,nrpt,qtor,coskr, sinkr)
    5861                 :             : 
    5862                 :             : !Arguments -------------------------------
    5863                 :             : !scalars
    5864                 :             :  integer,intent(in) :: natom,nqpt,nrpt,qtor
    5865                 :             : !arrays
    5866                 :             :  real(dp),intent(in) :: wghatm(natom,natom,nrpt)
    5867                 :             :  real(dp),intent(inout) :: gam_qpt(2,3*natom*3*natom,nqpt)
    5868                 :             :  real(dp),intent(inout) :: gam_rpt(2,3*natom*3*natom,nrpt)
    5869                 :             :  real(dp),intent(in) :: coskr(nqpt,nrpt)
    5870                 :             :  real(dp),intent(in) :: sinkr(nqpt,nrpt)
    5871                 :             : 
    5872                 :             : !Local variables -------------------------
    5873                 :             : !scalars
    5874                 :             :  integer :: iatom,idir,ip,iqpt,irpt,jatom,jdir
    5875                 :             :  real(dp) :: im,re
    5876                 :             :  character(len=500) :: msg
    5877                 :             : ! *********************************************************************
    5878                 :             : 
    5879                 :       26898 :  select case (qtor)
    5880                 :             :  case (1)
    5881                 :             :    ! Recip to real space
    5882   [ +  +  +  +  :      428974 :    gam_rpt(:,:,:) = zero
                   +  + ]
    5883         [ +  + ]:       11392 :    do irpt=1,nrpt
    5884         [ +  + ]:     1387296 :      do iqpt=1,nqpt
    5885                 :             :        ! Get the phase factor with normalization!
    5886                 :     1375904 :        re=coskr(iqpt,irpt)
    5887                 :     1375904 :        im=sinkr(iqpt,irpt)
    5888         [ +  + ]:    14078031 :        do ip=1,3*natom*3*natom
    5889                 :             :          ! Real and imaginary part of the real-space gam matrices
    5890                 :    12690936 :          gam_rpt(1,ip,irpt) = gam_rpt(1,ip,irpt) + re*gam_qpt(1,ip,iqpt) + im*gam_qpt(2,ip,iqpt)
    5891                 :    14066840 :          gam_rpt(2,ip,irpt) = gam_rpt(2,ip,irpt) + re*gam_qpt(2,ip,iqpt) - im*gam_qpt(1,ip,iqpt)
    5892                 :             :        end do
    5893                 :             :      end do
    5894                 :             :    end do
    5895   [ +  +  +  +  :      428974 :    gam_rpt = gam_rpt/nqpt
                   +  + ]
    5896                 :             : 
    5897                 :             :  case (0)
    5898                 :             :    ! Recip space from real space
    5899   [ +  +  +  +  :     1073346 :    gam_qpt(:,:,:)=zero
                   +  + ]
    5900                 :             : 
    5901         [ +  + ]:     1590618 :    do irpt=1,nrpt
    5902         [ +  + ]:     3154539 :      do iqpt=1,nqpt
    5903                 :             : 
    5904         [ +  + ]:     4784088 :        do iatom=1,natom
    5905         [ +  + ]:     5061063 :          do jatom=1,natom
    5906                 :     1840896 :            re = coskr(iqpt,irpt)*wghatm(iatom,jatom,irpt)
    5907                 :     1840896 :            im = sinkr(iqpt,irpt)*wghatm(iatom,jatom,irpt)
    5908                 :             : 
    5909         [ +  + ]:     9019830 :            do idir=1,3
    5910         [ +  + ]:    23931648 :              do jdir=1,3
    5911                 :             :                ! Get phase factor
    5912                 :             : 
    5913                 :    16568064 :                ip= jdir + (jatom-1)*3 + (idir-1)*3*natom + (iatom-1)*9*natom
    5914                 :             :                ! Real and imaginary part of the interatomic forces
    5915                 :    16568064 :                gam_qpt(1,ip,iqpt) = gam_qpt(1,ip,iqpt) + re*gam_rpt(1,ip,irpt) - im*gam_rpt(2,ip,irpt)
    5916                 :    22090752 :                gam_qpt(2,ip,iqpt) = gam_qpt(2,ip,iqpt) + im*gam_rpt(1,ip,irpt) + re*gam_rpt(2,ip,irpt)
    5917                 :             :              end do ! end jdir
    5918                 :             :            end do ! end idir
    5919                 :             :          end do
    5920                 :             :        end do ! end iatom
    5921                 :             : 
    5922                 :             :      end do ! end iqpt
    5923                 :             :    end do ! end irpt
    5924                 :             : 
    5925                 :             :  case default
    5926                 :           0 :    write(msg,'(a,i0,a)' )'The only allowed values for qtor are 0 or 1, while qtor= ',qtor,' has been required.'
    5927      [ +  +  - ]:       26898 :    ABI_BUG(msg)
    5928                 :             :  end select
    5929                 :             : 
    5930                 :       26898 : end subroutine ftgam
    5931                 :             : !!***
    5932                 :             : 
    5933                 :             : !!****f* m_dynmat/ftgam_init
    5934                 :             : !!
    5935                 :             : !! NAME
    5936                 :             : !! ftgam_init
    5937                 :             : !!
    5938                 :             : !! FUNCTION
    5939                 :             : !!  Generates the sin and cos phases for the Fourier transform of the gkk matrices
    5940                 :             : !!
    5941                 :             : !! INPUTS
    5942                 :             : !! gprim = reciprocal space vectors to get cartesian coord for qpt
    5943                 :             : !! nqpt= Number of q points in the Brillouin zone
    5944                 :             : !! nrpt= Number of R points in the Big Box
    5945                 :             : !! rpt(3,nprt)= Canonical coordinates of the R points in the unit cell
    5946                 :             : !!           These coordinates are normalized (=> * acell(3)!!)
    5947                 :             : !! qpt_full(3,nqpt)= Reduced coordinates of the q vectors in reciprocal space
    5948                 :             : !!           if qtor=0 these vectors are read in the input file
    5949                 :             : !!
    5950                 :             : !! OUTPUT
    5951                 :             : !! coskr, sinkr = cosine and sine of phase factors for given r and q points
    5952                 :             : !!
    5953                 :             : !! SOURCE
    5954                 :             : 
    5955                 :        1715 : subroutine ftgam_init (gprim,nqpt,nrpt,qpt_full,rpt,coskr, sinkr)
    5956                 :             : 
    5957                 :             : !Arguments -------------------------------
    5958                 :             : !scalars
    5959                 :             :  integer,intent(in) :: nqpt,nrpt
    5960                 :             : !arrays
    5961                 :             :  real(dp),intent(in) :: gprim(3,3),rpt(3,nrpt),qpt_full(3,nqpt)
    5962                 :             :  real(dp),intent(out) :: coskr(nqpt,nrpt)
    5963                 :             :  real(dp),intent(out) :: sinkr(nqpt,nrpt)
    5964                 :             : 
    5965                 :             : !Local variables -------------------------
    5966                 :             : !scalars
    5967                 :             :  integer :: iqpt,irpt
    5968                 :             :  real(dp) :: kr
    5969                 :             : !arrays
    5970                 :             :  real(dp) :: kk(3)
    5971                 :             : ! *********************************************************************
    5972                 :             : 
    5973                 :             : ! Prepare the phase factors
    5974         [ +  + ]:       10311 :  do iqpt=1,nqpt
    5975                 :             :    ! Calculation of the k coordinates in Normalized Reciprocal coordinates
    5976   [ +  +  +  + ]:      111748 :    kk(:) = matmul(gprim,qpt_full(:,iqpt))
    5977         [ +  + ]:      417383 :    do irpt=1,nrpt
    5978                 :             :      ! Product of k and r
    5979         [ +  + ]:     1628288 :      kr =dot_product(kk,rpt(:,irpt))
    5980                 :      407072 :      coskr(iqpt,irpt)=cos(two_pi*kr)
    5981                 :      415668 :      sinkr(iqpt,irpt)=sin(two_pi*kr)
    5982                 :             :    end do
    5983                 :             :  end do
    5984                 :             : 
    5985                 :        1715 : end subroutine ftgam_init
    5986                 :             : !!***
    5987                 :             : 
    5988                 :             : !----------------------------------------------------------------------
    5989                 :             : 
    5990                 :             : !!****f* m_dynmat/msria_calc
    5991                 :             : !! NAME
    5992                 :             : !! msria_calc
    5993                 :             : !!
    5994                 :             : !! FUNCTION
    5995                 :             : !! Calculate the corrections on the zone-center IFCs and their derivatives with respect to the phonon
    5996                 :             : !! wavevector q to achieve both translational (acoustic sum rule) and rotational invariances,
    5997                 :             : !! i.e. there is not remanent forces on the atoms if they are moved or rotated globablly.
    5998                 :             : !! This function needs the dimensionality of the system (0D, 1D, 2D, ...) to work properly, as well
    5999                 :             : !! as the moment of the IFCs, i.e. Phi^(1). It can be obtained by a long wave calculation
    6000                 :             : !! or with the Fourier transform. Be careful for the second option that the non-analytical part
    6001                 :             : !! is not (yet) treated for the 1D and 2D cases; ideally this routine should only impacts the
    6002                 :             : !! short-range IFCs (and the long-range subtracted before entering this routine)
    6003                 :             : !!
    6004                 :             : !! INPUTS
    6005                 :             : !!  asr=(6 Impose accoustic sum rules + rotational invariance)
    6006                 :             : !!  crystal<type(crystal_t)>=Crystal structure parameters
    6007                 :             : !!  d2cart(2,3,natom,3,natom)= Dynamical matrices coming from the Derivative Data Base at Gamma
    6008                 :             : !!  d2dq (3,natom,3,natom,3): moment of IFCs (Phi^(1)) in cartesian coordinates
    6009                 :             : !!  sys_dim=System dimensionality (0D, 1D, ...) used for rotational invariance
    6010                 :             : !!  mpert =maximum number of ipert
    6011                 :             : !!  natom=number of atom
    6012                 :             : !!
    6013                 :             : !! OUTPUT
    6014                 :             : !! d2asr= (2,3,natom,3,natom) matrix used to store the correction needed to fulfill
    6015                 :             : !! the acoustic + rotational sum rule on IFCs.
    6016                 :             : !! d2dqmsr= (3,natom,3,natom,3) matrix used to store the correction on IFCs moments
    6017                 :             : !!
    6018                 :             : !! SOURCE
    6019                 :             : 
    6020                 :             : !!***
    6021                 :             : !
    6022                 :           2 : subroutine msria_calc(asr,crystal,d2asr,d2cart,d2dq,d2dqdq,d2dqmsr,d2dqdqmsr,sys_dim,mpert,natom)
    6023                 :             : !Arguments ------------------------------------
    6024                 :             : !scalars
    6025                 :             :  integer,intent(in) :: sys_dim,asr,mpert,natom
    6026                 :             :  type(crystal_t),intent(in) :: crystal
    6027                 :             : !arrays
    6028                 :             :  real(dp),intent(in) :: d2cart(2,3,mpert,3,mpert)
    6029                 :             :  real(dp),intent(in) :: d2dq(3,natom,3,natom,3)
    6030                 :             :  real(dp),intent(in) :: d2dqdq(3,natom,3,3,3)
    6031                 :             :  real(dp),intent(out) :: d2asr(2,3,natom,3,natom)
    6032                 :             :  real(dp),intent(out) :: d2dqmsr(3,natom,3,natom,3)
    6033                 :             :  real(dp),intent(out) :: d2dqdqmsr(3,natom,3,natom,3,3)
    6034                 :             : !Local variables-------------------------------
    6035                 :             : !scalars
    6036                 :             :  integer :: idir1,idir2,idir3,idir4,idir5,info,ipert1,ipert2,col,ncol,nrow,row
    6037                 :             :  character(len=500) :: msg,msg2
    6038                 :             :  integer :: bool_kdir(3), bool_ldir(3)
    6039                 :             : !arrays
    6040                 :           4 :  real(dp) :: tmp,tmp2,Levi_Civita(3,3,3), d2dqdqcart(3,natom,3,natom,3,3)
    6041                 :           4 :  real(dp) :: d2dqred(3,natom,3,natom,3),d2dqdqred(3,natom,3,natom,3,3)
    6042                 :           2 :  real(dp),allocatable :: msr(:,:,:),msr_init(:,:,:)
    6043                 :           2 :  real(dp),allocatable :: d2cart_vec(:),rcond(:,:),cond(:)
    6044                 :           2 :  real(dp),allocatable :: mat_tmp(:,:),mat_tmp2(:,:),mat_tmp3(:,:),d2cart_sol(:),umat(:,:),vtmat(:,:)
    6045                 :           2 :  real(dp),allocatable :: vmat(:,:),sing(:),work(:),sing1(:,:),sing2(:,:)
    6046                 :             : 
    6047                 :             : ! *********************************************************************
    6048         [ -  + ]:           2 :  if(asr/=6)then
    6049                 :             :    write(msg,'(3a,i0)')&
    6050                 :           0 :    'The argument asr should be 6,',ch10, 'however, asr = ',asr
    6051                 :           0 :    ABI_BUG(msg)
    6052                 :             :  end if
    6053                 :             : 
    6054         [ +  - ]:           2 :  if (asr==6)then
    6055                 :           2 :    write(msg, '(a,a,a,a,a,a,a,a)' ) ch10, &
    6056                 :           2 :    ' Imposition of the ASR + rotational invariance for the interatomic forces (AMSR)', ch10, &
    6057                 :           2 :    ' Rotational invariance impose conditions on the IFCs moments and their derivatives',ch10,&
    6058                 :           2 :    ' At the moment, because of missing long-range contributions to the second IFCs derivatives',ch10,&
    6059                 :           4 :    ' rotational invariance is only imposed on the first-derivatives (first-order condition)'
    6060                 :           2 :    call wrtout(std_out,msg)
    6061                 :             :  end if
    6062                 :           2 :  bool_kdir = 0
    6063                 :           2 :  bool_ldir = 0
    6064                 :             :  ! When periodic, additional variable spaces coming from dynamical matrices derivatives
    6065   [ -  -  -  +  :           2 :  if (sys_dim == 1) then ! 3D
             -  -  -  +  
                      - ]
    6066         [ #  # ]:           0 :     bool_kdir = 0 ; bool_ldir = 1
    6067                 :           0 :     msg2=' 3D treatment'
    6068                 :             :  elseif (sys_dim == 2) then ! 2D yz
    6069                 :           0 :     bool_kdir(1) = 1 ; bool_ldir(2) = 1 ; bool_ldir(3) = 1
    6070                 :           0 :     msg2=' 2D with x as out-of-plane direction'
    6071                 :             :  elseif (sys_dim == 3) then ! 2D xz
    6072                 :           0 :     bool_kdir(2) = 1 ; bool_ldir(1) = 1 ; bool_ldir(3) = 1
    6073                 :           0 :     msg2=' 2D with y as out-of-plane direction'
    6074                 :             :  elseif (sys_dim == 4) then ! 2D xy
    6075                 :           1 :     bool_kdir(3) = 1 ; bool_ldir(1) = 1 ; bool_ldir(2) = 1
    6076                 :           1 :     msg2=' 2D with z as out-of-plane direction'
    6077                 :             :  elseif (sys_dim == 5) then ! 1D x
    6078                 :           0 :     bool_kdir(2) = 1 ; bool_kdir(3) = 1 ; bool_ldir(1) = 1
    6079                 :           0 :     msg2=' 1D with x as periodic direction'
    6080                 :             :  elseif (sys_dim == 6) then ! 1D y
    6081                 :           0 :     bool_kdir(1) = 1 ; bool_kdir(2) = 1 ; bool_ldir(2) = 1
    6082                 :           0 :     msg2=' 1D with y as periodic direction'
    6083                 :             :  elseif (sys_dim == 7) then ! 1D z
    6084                 :           0 :     bool_kdir(1) = 1 ;  bool_kdir(2) = 1 ; bool_ldir(3) = 1
    6085                 :           0 :     msg2=' 1D with z as periodic direction'
    6086                 :             :  elseif (sys_dim == 8) then ! Molecule
    6087         [ +  + ]:           4 :     bool_kdir = 1 ; bool_ldir = 0
    6088                 :           1 :     msg2=' 0D treatment (molecules)'
    6089                 :             :  else
    6090                 :             :     write(msg,'(3a,i0)')&
    6091                 :           0 :    'The argument sys_dim should be between 1 and 8,',ch10, 'however, sys_dim = ',sys_dim
    6092                 :           0 :    ABI_BUG(msg)
    6093                 :             :  end if
    6094                 :             : 
    6095                 :           2 :  write(msg, '(a,a)' ) ch10, trim(msg2)
    6096                 :           2 :  call wrtout(std_out,msg)
    6097                 :             : 
    6098                 :             :  ! Matrix sizing for pseudoinverse and alocation of corresponding matrix
    6099                 :           2 :  nrow = 3+2*3*3*natom ! 9*natom conditions for ASR, 9*natom+3 conditions for MSR
    6100                 :           2 :  nrow = nrow +4*(3*natom)**2 ! + Hermiticity
    6101                 :             : 
    6102                 :             :  ncol = (3*natom)**2 ! 9*natom**2 variable workspace (for dynamical matrices, initial)
    6103                 :             :  ncol = ncol + 3*(3*natom)**2 ! Aditional variable space coming from dD/dq (only for periodic systems)
    6104                 :           2 :  ncol = ncol + 9*(3*natom)**2 ! d2D/dqdq
    6105   [ -  +  +  -  :           8 :  ABI_MALLOC(msr,(1:3,1:natom,1:3))
          +  -  +  -  +  
             -  -  +  -  
                      + ]
    6106   [ -  +  +  -  :           4 :  ABI_MALLOC(msr_init,(1:3,1:natom,1:3))
             -  +  -  + ]
    6107   [ -  +  +  -  :           6 :  ABI_MALLOC(d2cart_vec,(1:ncol))
          +  -  +  -  -  
                +  -  + ]
    6108   [ -  +  +  -  :           4 :  ABI_MALLOC(d2cart_sol,(1:ncol))
             -  +  -  + ]
    6109   [ -  +  +  -  :           6 :  ABI_MALLOC(cond,(1:nrow))
          +  -  +  -  -  
                +  -  + ]
    6110   [ -  +  +  -  :           8 :  ABI_MALLOC(rcond,(1:nrow,1:ncol))
          -  +  +  -  +  
          -  +  -  -  +  
                   -  + ]
    6111         [ +  + ]:        2927 :  d2cart_vec=0d0
    6112         [ +  + ]:        2927 :  d2cart_sol=0d0
    6113         [ +  + ]:        1034 :  cond = 0d0
    6114   [ +  +  +  + ]:     1622792 :  rcond = 0d0
    6115                 :             : 
    6116                 :           2 :  Levi_Civita(:,:,:)=zero
    6117                 :           2 :  Levi_Civita(1,2,3)=+1 ; Levi_Civita(2,3,1)=+1 ; Levi_Civita(3,1,2)=+1
    6118                 :           2 :  Levi_Civita(3,2,1)=-1 ; Levi_Civita(1,3,2)=-1 ; Levi_Civita(2,1,3)=-1
    6119                 :             : 
    6120                 :             :  ! We only have access to \sum d^2 Phi(kappa alpha, kappa' beta)/dqdq through the
    6121                 :             :  ! long-wavelength driver, we need to construct the full tensor. Here we split
    6122                 :             :  ! an equal contribution on all atoms
    6123   [ +  +  +  +  :        2978 :  d2dqdqcart(:,:,:,:,:,:)=zero
          +  +  +  +  +  
                +  +  + ]
    6124         [ +  + ]:           9 :  do ipert1=1,natom
    6125         [ +  + ]:          30 :    do idir1=1,3
    6126         [ +  + ]:          91 :      do idir2=1,3
    6127         [ +  + ]:         309 :        do ipert2=1,natom
    6128         [ +  + ]:         963 :          do idir3=1,3
    6129                 :             :              d2dqdqcart(idir1,ipert1,idir2,ipert1,idir3,idir3)=&
    6130                 :         900 :                      -two*d2dqdq(idir1,ipert1,idir2,idir3,idir3)/dble(natom)
    6131                 :             :          end do
    6132                 :             :        end do
    6133                 :             :      end do
    6134                 :             :    end do
    6135                 :             :  end do
    6136                 :             :  ! Convert d2dq and d2dqdq in relative coordinates with respect to q
    6137   [ +  +  +  +  :         992 :  d2dqred = zero
          +  +  +  +  +  
                      + ]
    6138   [ +  +  +  +  :        2978 :  d2dqdqred = zero
          +  +  +  +  +  
                +  +  + ]
    6139         [ +  + ]:           8 :  do idir1=1,3
    6140         [ +  + ]:          26 :    do idir2=1,3
    6141   [ +  +  +  +  :        2970 :      d2dqred(:,:,:,:,idir1)=d2dqred(:,:,:,:,idir1)+d2dq(:,:,:,:,idir2)*crystal%gprimd(idir2,idir1)
             +  +  +  + ]
    6142         [ +  + ]:          78 :      do idir3=1,3
    6143         [ +  + ]:         234 :        do idir4=1,3
    6144                 :             :          d2dqdqred(:,:,:,:,idir2,idir4)=d2dqdqred(:,:,:,:,idir2,idir4)+&
    6145   [ +  +  +  +  :       26784 :          d2dqdqcart(:,:,:,:,idir1,idir3)*crystal%gprimd(idir1,idir2)*crystal%gprimd(idir3,idir4)
             +  +  +  + ]
    6146                 :             :        end do
    6147                 :             :      end do
    6148                 :             :    end do
    6149                 :             :  end do
    6150                 :             :  ! Now building the condition matrix
    6151         [ +  + ]:           8 :  do idir1=1,3
    6152         [ +  + ]:          29 :   do ipert1=1,natom
    6153         [ +  + ]:          90 :     do idir2=1,3
    6154         [ +  + ]:         309 :       do ipert2=1,natom
    6155                 :         225 :         col= ipert2+natom*(idir2-1)+3*natom*(ipert1-1)+3*natom**2*(idir1-1)
    6156                 :         225 :         d2cart_vec(col) = d2cart(1,idir1,ipert1,idir2,ipert2)
    6157                 :         225 :         row= idir2+3*(ipert1-1)+3*natom*(idir1-1) ! Acoustic sum rule
    6158                 :         225 :         rcond(row,col) = one ! Sum of IFCs along ipert2 = 0
    6159                 :             :         ! Rotational invariance
    6160         [ +  + ]:         900 :         do idir3=1,3
    6161                 :             :           ! Treat separately confined and periodic directions
    6162         [ +  + ]:         675 :           if ( bool_kdir(idir3) == 1) then ! confined direction
    6163         [ +  + ]:        1548 :             do idir4 = 1,3
    6164                 :        1161 :                 col= ipert2+natom*(idir2-1)+3*natom*(ipert1-1)+3*natom**2*(idir1-1)
    6165                 :        1161 :                 row = 9*natom+idir4+3*(ipert1-1)+3*natom*(idir1-1)
    6166                 :             :                 rcond(row,col) = rcond(row,col)+ & ! first moment of IFCs
    6167                 :        1548 :                 (crystal%xcart(idir3,ipert2)-crystal%xcart(idir3,ipert1))*Levi_Civita(idir2,idir3,idir4)
    6168                 :             :             end do
    6169                 :             :             ! Conditions on the second moments of IFCs
    6170                 :             :             ! In molecules, already fulfilled with rotational invariance
    6171                 :             :             ! For 1D systems, should only consider pair of direction when 1 is
    6172                 :             :             ! periodic, the other is not. Currently desactivated
    6173                 :             :             if (idir1 == idir2 .and. bool_ldir(idir1) ==1) then !
    6174                 :             :               col= ipert2+natom*(idir2-1)+3*natom*(ipert1-1)+3*natom**2*(idir1-1)
    6175                 :             :               row = 2*9*natom+idir2 ! second moment of IFCs
    6176                 :             :               ! Currently desactivated because long-range electrostatics, only need to uncomment
    6177                 :             :               ! when it will be available.
    6178                 :             :               !rcond(row,col) = -(crystal%xcart(idir3,ipert2)-crystal%xcart(idir3,ipert1))**2
    6179                 :             :               col= ipert1+natom*(idir1-1)+3*natom*(ipert2-1)+3*natom**2*(idir2-1)
    6180                 :             :               !rcond(row,col) = -(crystal%xcart(idir3,ipert2)-crystal%xcart(idir3,ipert1))**2
    6181                 :             :             end if
    6182                 :             :           end if
    6183         [ +  + ]:         900 :           if ( bool_ldir(idir3) == 1 ) then ! periodic direction
    6184                 :             :             ! Initialize the IFCs derivatives
    6185                 :         288 :             col= (3*natom)**2*idir3+ipert2+natom*(idir2-1)+3*natom*(ipert1-1)+3*natom**2*(idir1-1)
    6186                 :         288 :             d2cart_vec(col) = d2dqred(idir1,ipert1,idir2,ipert2,idir3)
    6187         [ +  + ]:        1152 :             do idir5 = 1,3
    6188         [ +  + ]:        3744 :               do idir4 = 1,3
    6189                 :        2592 :                 row = 9*natom+idir4+3*(ipert1-1)+3*natom*(idir1-1)
    6190                 :        3456 :                 rcond(row,col) = rcond(row,col)+ Levi_Civita(idir2,idir5,idir4)*crystal%rprimd(idir5,idir3)!/two_pi
    6191                 :             :               end do
    6192                 :             :             end do
    6193         [ +  + ]:        1152 :             do idir4=1,3
    6194                 :         288 :               if ( bool_ldir(idir4) == 1 ) then ! periodic direction
    6195                 :             :                 col= 4*(3*natom)**2+(3*natom)**2*3*(idir4-1)+&
    6196                 :         864 :                 (3*natom)**2*(idir3-1)+ipert2+natom*(idir2-1)+3*natom*(ipert1-1)+3*natom**2*(idir1-1)
    6197                 :             :                 !d2cart_vec(col) = d2dqdqred(idir1,ipert1,idir2,ipert2,idir3,idir4)
    6198                 :             :               end if
    6199                 :             :             end do
    6200   [ +  +  +  + ]:         288 :             if (idir2 == idir1 .and. bool_kdir(idir1)==1) then
    6201         [ +  + ]:         128 :               do idir4=1,3
    6202                 :             :                 col= 4*(3*natom)**2+(3*natom)**2*3*(idir4-1)+&
    6203                 :          96 :                 (3*natom)**2*(idir4-1)+ipert2+natom*(idir1-1)+3*natom*(ipert1-1)+3*natom**2*(idir1-1)
    6204                 :          96 :                 row = 2*9*natom+idir3 ! second moment of IFCs
    6205                 :             :                 !rcond(row,col) =  crystal%rprimd(idir4,idir3)**2!/two_pi
    6206                 :             :                 col= 4*(3*natom)**2+(3*natom)**2*3*(idir4-1)+&
    6207                 :         128 :                 (3*natom)**2*(idir4-1)+ipert1+natom*(idir1-1)+3*natom*(ipert2-1)+3*natom**2*(idir1-1)
    6208                 :             :                 !rcond(row,col) =  crystal%rprimd(idir4,idir3)**2!/two_pi
    6209                 :             :               end do
    6210                 :             :             end if
    6211                 :             :           end if
    6212                 :             :         end do
    6213                 :             :         ! Additionally, add the condition of matrix Hermiticity, both on IFCs and their derivatives
    6214                 :         225 :         col= ipert2+natom*(idir2-1)+3*natom*(ipert1-1)+3*natom**2*(idir1-1)
    6215                 :         225 :         row= 3+2*(9*natom)+ipert2+natom*(idir2-1)+3*natom*(ipert1-1)+3*natom**2*(idir1-1)
    6216                 :         225 :         rcond(row,col) = rcond(row,col)+ one ! Hermicity
    6217                 :         225 :         col= ipert1+natom*(idir1-1)+3*natom*(ipert2-1)+3*natom**2*(idir2-1)
    6218                 :         225 :         rcond(row,col) = rcond(row,col)- one ! Hermicity
    6219         [ +  + ]:         963 :          do idir3=1,3
    6220                 :         675 :             row= 3+2*(9*natom)+ipert2+natom*(idir2-1)+3*natom*(ipert1-1)+3*natom**2*(idir1-1)+9*natom**2*(idir3)
    6221                 :         675 :             col= (3*natom)**2*idir3+ipert2+natom*(idir2-1)+3*natom*(ipert1-1)+3*natom**2*(idir1-1)
    6222                 :         675 :             rcond(row,col) = rcond(row,col)+ one
    6223                 :         675 :             col= (3*natom)**2*idir3+ipert1+natom*(idir1-1)+3*natom*(ipert2-1)+3*natom**2*(idir2-1)
    6224                 :         900 :             rcond(row,col) = rcond(row,col)+ one
    6225                 :             :          end do
    6226                 :             :        end do
    6227                 :             :      end do
    6228                 :             :    end do
    6229                 :             :  end do
    6230                 :             : 
    6231                 :             : 
    6232                 :             : ! Use LAPACK singular value decomposition
    6233   [ -  +  +  -  :           4 :  ABI_MALLOC(sing,(1:nrow))
             -  +  -  + ]
    6234   [ -  +  +  -  :           8 :  ABI_MALLOC(umat,(1:nrow,1:nrow))
          -  +  +  -  +  
          -  +  -  -  +  
                   -  + ]
    6235   [ -  +  +  -  :           8 :  ABI_MALLOC(vtmat,(1:ncol,1:ncol))
          -  +  +  -  +  
          -  +  -  -  +  
                   -  + ]
    6236   [ -  +  +  -  :           6 :  ABI_MALLOC(work,(1:5*max(nrow,ncol)))
          +  -  +  -  -  
                +  -  + ]
    6237                 :             :  call dgesvd('A','A',nrow,ncol,rcond,nrow,sing,umat,nrow, &
    6238                 :           2 :          vtmat, ncol, work,5*max(nrow,ncol),info)
    6239         [ -  + ]:           2 :  ABI_CHECK(info == 0, sjoin('dgesvd returned:', itoa(info)))
    6240         [ -  + ]:           2 :  ABI_FREE(umat)
    6241         [ -  + ]:           2 :  ABI_FREE(work)
    6242                 :             : 
    6243                 :           2 :  write(msg, '(a,es16.8,es16.8)' )' Largest and smallest values from Singular Value Decomposition', sing(1), sing(nrow)
    6244         [ +  + ]:           4 :  call wrtout([std_out], msg)
    6245                 :             : 
    6246   [ -  +  +  -  :           8 :  ABI_MALLOC(vmat,(1:ncol,1:ncol))
          -  +  +  -  +  
          -  +  -  -  +  
                   -  + ]
    6247   [ -  +  +  -  :           8 :  ABI_MALLOC(sing1,(1:nrow,1:ncol))
          -  +  +  -  +  
          -  +  -  -  +  
                   -  + ]
    6248   [ -  +  +  -  :           6 :  ABI_MALLOC(sing2,(1:ncol,1:nrow))
          -  +  +  -  -  
                +  -  + ]
    6249   [ +  +  +  + ]:     4616120 :  vmat = zero
    6250   [ +  +  +  + ]:     1622792 :  sing1 = zero
    6251   [ +  +  +  + ]:     1620899 :  sing2 = zero
    6252         [ +  + ]:        2927 :  do ipert1=1,ncol
    6253         [ +  + ]:     4616120 :    do ipert2 =1,ncol
    6254                 :     4616118 :      vmat(ipert1,ipert2) = vtmat(ipert2,ipert1)
    6255                 :             :    end do
    6256                 :             :  end do
    6257                 :             :  ! To compute the pseudoinverse, product of the singular matrix with its inverse
    6258         [ +  + ]:        1034 :  do ipert1=1,min(nrow,ncol)
    6259                 :        1032 :    sing1(ipert1,ipert1) = sing(ipert1)
    6260         [ +  + ]:        1034 :    if (sing(ipert1)>tol12) then ! Avoids numerical problems
    6261                 :         576 :      sing2(ipert1,ipert1) = 1_dp/sing(ipert1)
    6262                 :             :    end if
    6263                 :             :  end do
    6264                 :             : 
    6265   [ -  +  +  -  :           6 :  ABI_MALLOC(mat_tmp,(1:ncol,1:ncol))
          -  +  +  -  -  
                +  -  + ]
    6266   [ -  +  +  -  :           6 :  ABI_MALLOC(mat_tmp2,(1:ncol,1:ncol))
          -  +  +  -  -  
                +  -  + ]
    6267   [ -  +  +  -  :           6 :  ABI_MALLOC(mat_tmp3,(1:ncol,1:ncol))
          -  +  +  -  -  
                +  -  + ]
    6268                 :             : 
    6269   [ -  +  -  -  :           2 :  mat_tmp = matmul(sing2,sing1)
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
             -  -  -  - ]
    6270   [ -  +  -  -  :           2 :  mat_tmp2 = matmul(vmat,mat_tmp)
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
             -  -  -  -  
                      - ]
    6271   [ -  +  -  -  :           2 :  mat_tmp3 = matmul(mat_tmp2,vtmat)
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
                   -  - ]
    6272                 :             : 
    6273                 :             :  ! Change of IFCs and its derivatives
    6274   [ +  -  -  +  :     4619045 :  d2cart_sol = matmul(mat_tmp3,d2cart_vec)
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  +  +  +  +  
                   +  + ]
    6275         [ -  + ]:           2 :  ABI_FREE(sing)
    6276         [ -  + ]:           2 :  ABI_FREE(sing1)
    6277         [ -  + ]:           2 :  ABI_FREE(vmat)
    6278         [ -  + ]:           2 :  ABI_FREE(sing2)
    6279         [ -  + ]:           2 :  ABI_FREE(mat_tmp)
    6280         [ -  + ]:           2 :  ABI_FREE(mat_tmp2)
    6281         [ -  + ]:           2 :  ABI_FREE(mat_tmp3)
    6282                 :             : 
    6283                 :             :  ! Now unravel the IFCs and derivatives in arrays
    6284                 :             : 
    6285   [ +  +  +  +  :         780 :  d2asr = zero
          +  +  +  +  +  
                      + ]
    6286   [ +  +  +  +  :         992 :  d2dqmsr = zero
          +  +  +  +  +  
                      + ]
    6287   [ +  +  +  +  :        2978 :  d2dqdqmsr = zero
          +  +  +  +  +  
                +  +  + ]
    6288         [ +  + ]:           8 :  do idir1=1,3
    6289         [ +  + ]:          29 :    do ipert1=1, natom
    6290         [ +  + ]:          90 :      do idir2=1,3
    6291         [ +  + ]:         309 :        do ipert2=1, natom
    6292                 :         225 :          col = ipert2+natom*(idir2-1)+3*natom*(ipert1-1)+3*natom**2*(idir1-1)
    6293                 :         225 :          d2asr(1,idir1,ipert1,idir2,ipert2) = d2cart_sol(col)
    6294         [ +  + ]:         963 :          do idir3=1,3
    6295                 :         675 :            col = (3*natom)**2*idir3+ipert2+natom*(idir2-1)+3*natom*(ipert1-1)+3*natom**2*(idir1-1)
    6296                 :         675 :            d2dqmsr(idir1,ipert1,idir2,ipert2,idir3) = d2cart_sol(col)
    6297         [ +  + ]:        2925 :            do idir4=1,3
    6298                 :             :              col = 4*(3*natom)**2+3*(3*natom)**2*(idir4-1)+&
    6299                 :        2700 :              (3*natom)**2*(idir3-1)+ipert2+natom*(idir2-1)+3*natom*(ipert1-1)+3*natom**2*(idir1-1)
    6300                 :             :              !d2dqdqmsr(idir1,ipert1,idir2,ipert2,idir3,idir4) = d2cart_sol(col)
    6301                 :             :            end do
    6302                 :             :          end do
    6303                 :             :        end do
    6304                 :             :      end do
    6305                 :             :    end do
    6306                 :             :  end do
    6307                 :             : 
    6308                 :             : 
    6309   [ +  +  +  +  :          92 :  msr = zero
                   +  + ]
    6310   [ +  +  +  +  :          92 :  msr_init = zero
                   +  + ]
    6311         [ +  + ]:           9 :  do ipert1=1, natom
    6312         [ +  + ]:          30 :    do idir1=1,3
    6313         [ +  + ]:          91 :      do idir2=1,3
    6314         [ +  + ]:         309 :        do ipert2=1, natom
    6315         [ +  + ]:         963 :          do idir3=1,3
    6316         [ +  + ]:         675 :            if ( bool_kdir(idir3) == 1) then ! Contribution from zone-center
    6317                 :         387 :              tmp = d2cart(1,idir1,ipert1,idir2,ipert2)
    6318                 :         387 :              tmp2 = tmp-d2asr(1,idir1,ipert1,idir2,ipert2)
    6319         [ +  + ]:        1548 :              do idir4 = 1,3
    6320                 :             :                msr_init(idir1,ipert1,idir4)=msr_init(idir1,ipert1,idir4)+&
    6321                 :        1161 :                tmp*(crystal%xcart(idir3,ipert2)-crystal%xcart(idir3,ipert1))*Levi_Civita(idir2,idir3,idir4)
    6322                 :             :                msr(idir1,ipert1,idir4)=msr(idir1,ipert1,idir4)+&
    6323                 :        1548 :                tmp2*(crystal%xcart(idir3,ipert2)-crystal%xcart(idir3,ipert1))*Levi_Civita(idir2,idir3,idir4)
    6324                 :             :              end do
    6325                 :             :            end if
    6326         [ +  + ]:         900 :            if ( bool_ldir(idir3) == 1 ) then ! Contribution from dC/dq
    6327                 :         288 :              tmp =d2dqred(idir1,ipert1,idir2,ipert2,idir3)
    6328                 :         288 :              tmp2=tmp-d2dqmsr(idir1,ipert1,idir2,ipert2,idir3)
    6329         [ +  + ]:        1152 :              do idir4 = 1,3
    6330         [ +  + ]:        3744 :               do idir5 = 1,3
    6331                 :             :                 msr_init(idir1,ipert1,idir4)=msr_init(idir1,ipert1,idir4)+&
    6332                 :        2592 :                         tmp*crystal%rprimd(idir5,idir3)*Levi_Civita(idir2,idir5,idir4)
    6333                 :             :                 msr(idir1,ipert1,idir4)=msr(idir1,ipert1,idir4)+&
    6334                 :        3456 :                         tmp2*crystal%rprimd(idir5,idir3)*Levi_Civita(idir2,idir5,idir4)
    6335                 :             :               end do
    6336                 :             :             end do
    6337                 :             :            end if
    6338                 :             :          end do
    6339                 :             :        end do
    6340                 :             :      end do
    6341                 :             :    end do
    6342                 :             :  end do
    6343                 :           2 :  write(msg, '(a,a,a,a)' ) ch10, &
    6344                 :           2 :    ' Rotational invariance breaking, before and after imposition', ch10, &
    6345                 :           4 :    '    ipert1   idir1   idir2   torque initial  [Ha/Bohr]  torque final [Ha/Bohr]'
    6346         [ +  + ]:           6 :    call wrtout([std_out, ab_out],msg)
    6347         [ +  + ]:           9 :  do ipert1=1,natom
    6348         [ +  + ]:          30 :    do idir1=1,3
    6349         [ +  + ]:          91 :      do idir4=1,3
    6350                 :          63 :        write(msg, '(a,i0,a,i0,a,i0,a, es16.8,a,es16.8)') '     ', ipert1,'        ', idir1, &
    6351                 :         126 :               '        ', idir4 , '    ', msr_init(idir1,ipert1,idir4),'           ', msr(idir1,ipert1,idir4)
    6352         [ +  + ]:         210 :        call wrtout([std_out, ab_out],msg)
    6353                 :             :      end do
    6354                 :             :    end do
    6355                 :             :  end do
    6356                 :             : 
    6357         [ -  + ]:           2 :  ABI_FREE(msr)
    6358         [ -  + ]:           2 :  ABI_FREE(msr_init)
    6359         [ -  + ]:           2 :  ABI_FREE(d2cart_vec)
    6360         [ -  + ]:           2 :  ABI_FREE(d2cart_sol)
    6361         [ -  + ]:           2 :  ABI_FREE(vtmat)
    6362         [ -  + ]:           2 :  ABI_FREE(cond)
    6363         [ -  + ]:           2 :  ABI_FREE(rcond)
    6364                 :             : 
    6365                 :           2 : end subroutine msria_calc
    6366                 :             : 
    6367                 :             : !----------------------------------------------------------------------
    6368                 :             : 
    6369                 :             : !!****f* m_dynmat/msria_apply
    6370                 :             : !! NAME
    6371                 :             : !! msria_corr
    6372                 :             : !!
    6373                 :             : !! FUNCTION
    6374                 :             : !! Imposition of the Accoustic sum rule and rotational invariance on the InterAtomic Forces
    6375                 :             : !! respecting crystal symmetries. Note that when IFCs derivatives are estimated previously
    6376                 :             : !! based on the Fourier transforms, they do not strictly respect them; this is only solved
    6377                 :             : !! when using the IFCs derivatives from the LW driver. Eventually, if the latter are available,
    6378                 :             : !! correct the IFCs to match the ones from the LW driver close to the zone-center
    6379                 :             : !!
    6380                 :             : !! INPUTS
    6381                 :             : !! asr=(0 => no ASR, 1 or 2=> the diagonal element is modified to give the ASR,
    6382                 :             : !!      5 => impose hermitian solution using lapack call, 6 => rotational invariance)
    6383                 :             : !! d2asr=matrix used to store the correction needed to fulfill the acoustic sum rule.
    6384                 :             : !! d2dqmsr = same, but for the first IFCs moment for rotational invariance
    6385                 :             : !! d2dqdqmsr = same, but for the second IFCs moment for rotational invariance
    6386                 :             : !! mpert =maximum number of ipert
    6387                 :             : !! natom=number of atom
    6388                 :             : !! qphon(3,3)=wavevectors for the three possible phonons
    6389                 :             : !! crystal<type(crystal_t)>=Crystal structure parameters
    6390                 :             : !!
    6391                 :             : !! OUTPUT
    6392                 :             : !! Input/Output:
    6393                 :             : !! d2cart=matrix of second derivatives of total energy, in cartesian coordinates
    6394                 :             : !!
    6395                 :             : !! SOURCE
    6396                 :             : 
    6397                 :         162 : subroutine msria_apply(asr,d2asr,d2dqmsr,d2cart,mpert,natom,qphon,crystal)
    6398                 :             : 
    6399                 :             : !Arguments -------------------------------
    6400                 :             : !scalars
    6401                 :             :  integer,intent(in) :: asr,mpert,natom
    6402                 :             :  type(crystal_t),intent(in) :: crystal
    6403                 :             : !arrays
    6404                 :             :  real(dp),intent(in) :: d2dqmsr(3,natom,3,natom,3)!, d2dqdqmsr(3,natom,3,natom,3,3)
    6405                 :             :  real(dp),intent(in) :: d2asr(2,3,natom,3,natom), qphon(3,3)
    6406                 :             :  real(dp),intent(inout) :: d2cart(2,3,mpert,3,mpert)
    6407                 :             : !Local variables-------------------------------
    6408                 :             : !scalars
    6409                 :             :  integer :: idir1,idir2,ipert1,ipert2,idir3,ii,jj
    6410                 :           0 :  integer :: tiat,tjat,isym,indij(natom,natom),indij2(natom,natom,3)
    6411                 :             :  integer :: isgn, itirev,acc,acc2
    6412                 :         324 :  real(dp) :: qsym(3), qsym2(3), symcart(3,3,crystal%nsym),arg1,arg2
    6413                 :             :  real(dp) :: re,im,re2,im2,sumr,sumi,valr,vali,carttmp
    6414                 :         162 :  real(dp), allocatable :: pert(:,:,:,:,:,:), pert2(:,:,:,:,:,:,:)
    6415                 :             :  real(dp) :: Levi_Civita(3,3,3)
    6416                 :             : ! *********************************************************************
    6417   [ -  +  +  -  :         972 :  ABI_MALLOC(pert,(1:2,1:3,1:natom,1:3,1:natom,1:2*crystal%nsym))
          +  -  -  +  +  
          -  -  +  +  -  
          +  -  +  -  -  
                +  -  + ]
    6418   [ -  +  +  -  :         972 :  ABI_MALLOC(pert2,(1:2,1:3,1:natom,1:3,1:natom,1:2*crystal%nsym,1:3))
          -  +  +  -  -  
          +  +  -  +  -  
          +  -  +  -  -  
                +  -  + ]
    6419         [ -  + ]:         162 :  if (asr/=6) return
    6420                 :             :  Levi_Civita(:,:,:)=zero
    6421                 :             :  Levi_Civita(1,2,3)=+1 ; Levi_Civita(2,3,1)=+1 ; Levi_Civita(3,1,2)=+1
    6422                 :             :  Levi_Civita(3,2,1)=-1 ; Levi_Civita(1,3,2)=-1 ; Levi_Civita(2,1,3)=-1
    6423                 :             :  ! By convention, Fourier transform in ABINIT is only using the cell
    6424                 :             :  ! coordinates, not the reduced coordinates of the atoms
    6425                 :             :  ! The code that follows already take this into account
    6426                 :             :  ! for sake of legibility
    6427                 :             :  ! Define symmetry tensor for IFCs
    6428         [ +  + ]:        1454 :  do isym=1,crystal%nsym
    6429         [ +  + ]:        5330 :    do idir1=1,3
    6430         [ +  + ]:       15504 :      symcart(:,idir1,isym)=zero
    6431         [ +  + ]:       16796 :      do idir2=1,3
    6432         [ +  + ]:       50388 :        do idir3=1,3
    6433                 :             :          symcart(:,idir1,isym)=symcart(:,idir1,isym)+crystal%rprimd(:,idir2)&
    6434         [ +  + ]:      151164 :                  *crystal%gprimd(idir1,idir3)*crystal%symrel(idir2,idir3,isym)
    6435                 :             :        end do
    6436                 :             :      end do
    6437                 :             :    end do
    6438                 :             :  end do
    6439   [ +  +  +  +  :     5130792 :  pert = zero;  pert2 = zero
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
                   +  + ]
    6440   [ +  +  +  +  :       13576 :  indij = 0 ; indij2 = 0
          +  +  +  +  +  
                      + ]
    6441                 :             :  ! Need to loop over symmetries to properly impose rotational invariance
    6442         [ +  + ]:        1454 :  do isym=1,crystal%nsym
    6443         [ +  + ]:        4038 :    do itirev=1,2  ! loop over the time-reversal symmetry
    6444                 :        2584 :      isgn=3-2*itirev
    6445         [ +  + ]:       14204 :      do ipert1=1,natom
    6446         [ +  + ]:       54200 :        do ipert2=1,natom
    6447                 :       41288 :          tiat = crystal%indsym(4,isym,ipert1) ! symmetric atom of i
    6448                 :       41288 :          tjat = crystal%indsym(4,isym,ipert2) ! symmetric atom of j
    6449         [ +  + ]:      165152 :          qsym(:) = crystal%indsym(1:3,isym,ipert2)-crystal%indsym(1:3,isym,ipert1)
    6450         [ +  + ]:      165152 :          qsym= -isgn*qsym
    6451         [ +  + ]:      165152 :          arg1 = two_pi*DOT_PRODUCT(qsym,qphon(:,1))
    6452                 :       41288 :          acc=indij(tiat,tjat)+1
    6453                 :       41288 :          indij(tiat,tjat)=acc
    6454         [ +  + ]:      165152 :          do idir1=1,3
    6455         [ +  + ]:      536744 :            do idir2=1,3
    6456                 :      371592 :              sumr=zero
    6457                 :      371592 :              re = cos(arg1)
    6458                 :      371592 :              im = sin(arg1)
    6459         [ +  + ]:     1486368 :              do ii=1,3
    6460         [ +  + ]:     4830696 :                do jj=1,3
    6461                 :             : !                Correction from on-site and first-neighbors in the same cells (or images)
    6462                 :     4459104 :                   sumr=sumr+symcart(idir1,ii,isym)*symcart(idir2,jj,isym)*d2asr(1,ii,tiat,jj,tjat)
    6463                 :             :                   ! Second order desactivated because of missing contribution from electrostatics
    6464                 :             :                   ! simply uncomment when available
    6465                 :             :                   !do idir3=1,3
    6466                 :             :                   !  sumr=sumr-symcart(idir1,ii,isym)*symcart(idir2,jj,isym)*&
    6467                 :             :                   !          d2dqdqmsr(ii,tiat,jj,tjat,idir3,idir3)/four
    6468                 :             :                   !end do
    6469                 :             :                end do
    6470                 :             :              end do
    6471                 :      371592 :              valr = re*sumr
    6472                 :      371592 :              vali = im*sumr
    6473                 :      371592 :              pert(1,idir1,ipert1,idir2,ipert2,crystal%nsym*(itirev-1)+isym) = valr
    6474                 :      495456 :              pert(2,idir1,ipert1,idir2,ipert2,crystal%nsym*(itirev-1)+isym) = vali
    6475                 :             :            end do
    6476                 :             :          end do
    6477         [ +  + ]:      175480 :          do idir3=1,3
    6478                 :      123864 :            acc2=indij2(tiat,tjat,idir3)+1
    6479                 :      123864 :            indij2(tiat,tjat,idir3)=acc2
    6480         [ +  + ]:      495456 :            qsym2(:) = crystal%symrel(:,idir3,isym)
    6481         [ +  + ]:      495456 :            qsym2(:)=-isgn*(qsym2(:))
    6482         [ +  + ]:      495456 :            arg2 = two_pi*DOT_PRODUCT(qsym2,qphon(:,1))
    6483         [ +  + ]:      536744 :            do idir1=1,3
    6484         [ +  + ]:     1610232 :              do idir2=1,3
    6485                 :             :                sumi=zero
    6486                 :     4459104 :                sumr=zero
    6487         [ +  + ]:     4459104 :                do ii=1,3
    6488         [ +  + ]:    14492088 :                  do jj=1,3
    6489                 :             :                    ! second order desactivated
    6490                 :             :                    !sumr=sumr+symcart(idir1,ii,isym)*symcart(idir2,jj,isym)*&
    6491                 :             :                    !     d2dqdqmsr(ii,tiat,jj,tjat,idir3,idir3)/four
    6492                 :             :                    sumi=sumi+isgn*symcart(idir1,ii,isym)*symcart(idir2,jj,isym)*&
    6493                 :    13377312 :                         d2dqmsr(ii,tiat,jj,tjat,idir3)
    6494                 :             :                  end do
    6495                 :             :                end do
    6496                 :     1114776 :                im = -cos(arg1)*sin(arg2)
    6497                 :     1114776 :                re = sin(arg1)*sin(arg2)
    6498                 :     1114776 :                re2 = cos(arg1)*cos(two*arg2)
    6499                 :     1114776 :                im2 = sin(arg1)*cos(two*arg2)
    6500                 :     1114776 :                valr = re*sumi+re2*sumr
    6501                 :     1114776 :                vali = im*sumi+im2*sumr
    6502                 :     1114776 :                pert2(1,idir1,ipert1,idir2,ipert2,crystal%nsym*(itirev-1)+isym,idir3)= valr
    6503                 :     1486368 :                pert2(2,idir1,ipert1,idir2,ipert2,crystal%nsym*(itirev-1)+isym,idir3)= vali
    6504                 :             :              end do !idir1
    6505                 :             :            end do !idir2
    6506                 :             :          end do !idir3
    6507                 :             :        end do !ipert2
    6508                 :             :      end do !ipert1
    6509                 :             :    end do !itirev
    6510                 :             :  end do !isym
    6511         [ +  + ]:         809 :  do ipert1=1,natom
    6512         [ +  + ]:        2750 :    do idir1 =1,3
    6513         [ +  + ]:        8411 :      do idir2=1,3
    6514         [ +  + ]:       31029 :        do ipert2=1,natom
    6515         [ +  + ]:      214884 :          do isym=1,crystal%nsym
    6516         [ +  + ]:      580653 :            do itirev=1,2  ! loop over the time-reversal symmetry
    6517                 :      371592 :              isgn=3-2*itirev
    6518                 :             :              carttmp = d2cart(1,idir1,ipert1,idir2,ipert2)- &
    6519                 :      371592 :              pert(1,idir1,ipert1,idir2,ipert2,crystal%nsym*(itirev-1)+isym)/dble(indij(ipert1,ipert2))
    6520                 :      371592 :              d2cart(1,idir1,ipert1,idir2,ipert2) = carttmp
    6521                 :             :              carttmp = d2cart(2,idir1,ipert1,idir2,ipert2)- &
    6522                 :      371592 :              pert(2,idir1,ipert1,idir2,ipert2,crystal%nsym*(itirev-1)+isym)/dble(indij(ipert1,ipert2))
    6523                 :      371592 :              d2cart(2,idir1,ipert1,idir2,ipert2) = carttmp
    6524         [ +  + ]:     1672164 :              do idir3=1,3
    6525                 :             :                carttmp = d2cart(1,idir1,ipert1,idir2,ipert2)- &
    6526                 :     1114776 :                pert2(1,idir1,ipert1,idir2,ipert2,crystal%nsym*(itirev-1)+isym,idir3)/dble(indij2(ipert1,ipert2,idir3))
    6527                 :     1114776 :                d2cart(1,idir1,ipert1,idir2,ipert2) = carttmp
    6528                 :             :                carttmp = d2cart(2,idir1,ipert1,idir2,ipert2)- &
    6529                 :     1114776 :                pert2(2,idir1,ipert1,idir2,ipert2,crystal%nsym*(itirev-1)+isym,idir3)/dble(indij2(ipert1,ipert2,idir3))
    6530                 :     1486368 :                d2cart(2,idir1,ipert1,idir2,ipert2) = carttmp
    6531                 :             :              end do
    6532                 :             :            end do
    6533                 :             :          end do
    6534                 :             :        end do
    6535                 :             :      end do
    6536                 :             :    end do
    6537                 :             :  end do
    6538         [ -  + ]:         162 :  ABI_FREE(pert)
    6539         [ -  + ]:         162 :  ABI_FREE(pert2)
    6540   [ #  #  #  # ]:           0 : end subroutine msria_apply
    6541                 :             : !!***
    6542                 :             : end module m_dynmat
        

Generated by: LCOV version 2.3-1