TABLE OF CONTENTS


ABINIT/hermit [ Functions ]

[ Top ] [ Functions ]

NAME

 hermit

FUNCTION

 Take a matrix in hermitian storage mode (lower triangle stored)
 and redefine diagonal elements to impose Hermiticity
 (diagonal terms have to be real).
 If abs(Im(H(i,i)))>4096*machine precision, print error warning.
 (Typical 64 bit machine precision is 2^-52 or 2.22e-16)

COPYRIGHT

 Copyright (C) 1998-2017 ABINIT group (DCA, XG, GMR).
 This file is distributed under the terms of the
 GNU General Public License, see ~abinit/COPYING
 or http://www.gnu.org/copyleft/gpl.txt .
 For the initials of contributors, see ~abinit/doc/developers/contributors.txt .

INPUTS

  chmin(n*n+n)=complex hermitian matrix with numerical noise possibly
   rendering Im(diagonal elements) approximately 1e-15 or so
  ndim=size of complex hermitian matrix

OUTPUT

  chmout(n*n+n)=redefined matrix with strictly real diagonal elements.
   May be same storage location as chmin.
  ierr=0 if no problem, 1 if the imaginary part of some element
   too large (at present, stop in this case).

TODO

  Name is misleading, perhaps hermit_force_diago?
  Interface allows aliasing

PARENTS

      extrapwf,subdiago

CHILDREN

      wrtout

SOURCE

 43 #if defined HAVE_CONFIG_H
 44 #include "config.h"
 45 #endif
 46 
 47 #include "abi_common.h"
 48 
 49 
 50 subroutine hermit(chmin,chmout,ierr,ndim)
 51 
 52  use defs_basis
 53  use m_errors
 54 
 55 !This section has been created automatically by the script Abilint (TD).
 56 !Do not modify the following lines by hand.
 57 #undef ABI_FUNC
 58 #define ABI_FUNC 'hermit'
 59  use interfaces_14_hidewrite
 60 !End of the abilint section
 61 
 62  implicit none
 63 
 64 !Arguments ------------------------------------
 65 !scalars
 66  integer,intent(in) :: ndim
 67  integer,intent(out) :: ierr
 68 !arrays
 69  real(dp),intent(inout) :: chmin(ndim*ndim+ndim)
 70  real(dp),intent(inout) :: chmout(ndim*ndim+ndim)
 71 
 72 !Local variables-------------------------------
 73 !scalars
 74  integer,save :: mmesgs=20,nmesgs=0
 75  integer :: idim,merrors,nerrors
 76  real(dp),parameter :: eps=epsilon(0.0d0)
 77  real(dp) :: ch_im,ch_re,moduls,tol
 78  character(len=500) :: message
 79 
 80 ! *************************************************************************
 81 
 82  tol=4096.0d0*eps
 83 
 84  ierr=0
 85  merrors=0
 86 
 87 !Copy matrix into possibly new location
 88  chmout(:)=chmin(:)
 89 
 90 !Loop over diagonal elements of matrix (off-diag not altered)
 91  do idim=1,ndim
 92 
 93    ch_im=chmout(idim*idim+idim  )
 94    ch_re=chmout(idim*idim+idim-1)
 95 
 96 !  check for large absolute Im part and print warning when
 97 !  larger than (some factor)*(machine precision)
 98    nerrors=0
 99    if( abs(ch_im) > tol .and. abs(ch_im) > tol8*abs(ch_re)) nerrors=2
100    if( abs(ch_im) > tol .or. abs(ch_im) > tol8*abs(ch_re)) nerrors=1
101 
102    if( (abs(ch_im) > tol .and. nmesgs<mmesgs) .or. nerrors==2)then
103      write(message, '(3a,i0,a,es20.12,a,es20.12,a)' )&
104 &     'Input Hermitian matrix has nonzero relative Im part on diagonal:',ch10,&
105 &     'for component',idim,' Im part is',ch_im,', Re part is',ch_re,'.'
106      call wrtout(std_out,message,'PERS')
107      nmesgs=nmesgs+1
108    end if
109 
110    if( ( abs(ch_im) > tol8*abs(ch_re) .and. nmesgs<mmesgs) .or. nerrors==2)then
111      write(message, '(3a,i0,a,es20.12,a,es20.12,a)' )&
112 &     'Input Hermitian matrix has nonzero relative Im part on diagonal:',ch10,&
113 &     'for component',idim,' Im part is',ch_im,', Re part is',ch_re,'.'
114      call wrtout(std_out,message,'PERS')
115      nmesgs=nmesgs+1
116    end if
117 
118 !  compute modulus $= (\Re^2+\Im^2)^{1/2}$
119    moduls=sqrt(ch_re**2+ch_im**2)
120 
121 !  set Re part to modulus with sign of original Re part
122    chmout(idim*idim+idim-1)=sign(moduls,ch_re)
123 
124 !  set Im part to 0
125    chmout(idim*idim+idim)=zero
126 
127    merrors=max(merrors,nerrors)
128 
129  end do
130 
131  if(merrors==2)then
132    ierr=1
133    write(message, '(3a)' )&
134 &   'Imaginary part(s) of diagonal Hermitian matrix element(s) is too large.',ch10,&
135 &   'See previous messages.'
136    MSG_BUG(message)
137  end if
138 
139 end subroutine hermit