TABLE OF CONTENTS


ABINIT/m_model_screening [ Modules ]

[ Top ] [ Modules ]

NAME

 m_model_screening

FUNCTION

  Module containing functions for calculating and fitting model dielectric functions

COPYRIGHT

  Copyright (C) 2008-2024 ABINIT group (MS)
  This file is distributed under the terms of the
  GNU General Public License, see ~abinit/COPYING
  or http://www.gnu.org/copyleft/gpl.txt .

SOURCE

16 #if defined HAVE_CONFIG_H
17 #include "config.h"
18 #endif
19 
20 #include "abi_common.h"
21 
22 MODULE m_model_screening
23 
24  use defs_basis
25  use m_errors
26  use m_abicore
27 
28  use m_io_tools,       only : open_file
29 
30  implicit none
31 
32  private
33 
34  public :: im_screening         ! Calc. Drude-Lorentz model function from parameters.
35  public :: re_screening         ! Calc. Drude-Lorentz model function from parameters.
36  public :: re_and_im_screening  ! Calc. Drude-Lorentz model function from parameters.
37  public :: re_and_im_screening_with_phase  ! Calc. Drude-Lorentz model function from parameters.
38                                            !  with the addition of a phase
39  public :: sequential_fitting   ! Fit poles one by one
40  public :: init_peaks_from_grid ! find approximate expression for parameters from
41                                 !  chi0 or eps^-1 on a grid in the complex plane.
42  public :: init_peaks_even_dist ! Initial guess from even distributuin of peaks
43  public :: init_single_peak     ! Initialise a single peak from the maximum, the
44                                 !  origin, and the second value along the
45                                 !  imaginary axis
46 ! public :: int_screening        ! Find the integral along real or complex axis
47                                 !  from parameters.
48  public :: remove_phase
49 
50 CONTAINS  !==============================================================================

m_model_screening/find_peaks [ Functions ]

[ Top ] [ m_model_screening ] [ Functions ]

NAME

  find_peaks

FUNCTION

  Find the location of the highest peaks along gridlines starting at the real axis
  and then moving towards higher imaginary frequencies. Stop when enough
  peaks to satisfy the number of poles needed has been found

INPUTS

  omega      = (complex) Real and imaginary part of the frequency points
  fvals      = The function to be fitted in the complex plane
  nomega     = number of fit points
  nfreqre    = number or imaginary gridlines
  nfreqim    = number of real gridlines

OUTPUT

NOTES

SOURCE

846 subroutine find_peaks(fval,nomega,nfreqre,nfreqim,ploc,npoles,iline)
847 
848   implicit none
849 
850 !Arguments ------------------------------------
851 !scalars
852   integer,intent(in)     :: nomega,nfreqre,nfreqim,npoles
853   integer, intent(inout) :: iline
854 !arrays
855   integer    ,intent(inout) :: ploc(npoles)
856   complex(gwpc), intent(in) :: fval(nomega)
857 
858 !Local variables-------------------------------
859 !scalars
860   integer    :: ire,iim,ipoles
861   integer    :: idx1,idx2,idx3,ipol
862   real(gwp) :: val1,val2,val3
863 
864 !arrays
865   integer :: ploc_prev(npoles)
866   real    :: pval(npoles),pval_prev(npoles)
867 
868 ! *********************************************************************
869 
870   ploc=-1; ploc_prev=-1
871   pval=zero; pval_prev=zero; ipol=1; ipoles=0
872 
873 ! First do a line along the real axis
874   idx1 = 1; idx2 = 2
875   val1 = AIMAG(fval(idx1)); val2 = AIMAG(fval(idx2))
876   if (ABS(val1)>ABS(val2)) then
877     ipoles = ipoles + 1
878     ploc(1)=idx1; pval(1)=val1
879     write(std_out,*) ' pval:',pval
880     write(std_out,*) ' ploc:',ploc
881   end if
882   do ire=2,nfreqre-3
883     idx1 = ire; idx2 = idx1+1; idx3 = idx1+2
884     val1 = AIMAG(fval(idx1))
885     val2 = AIMAG(fval(idx2))
886     val3 = AIMAG(fval(idx3))
887     if (((val1<val2).AND.(val2>val3))) then
888       if (sign(1.0_gwp,val2)<zero) CYCLE
889       ipoles = ipoles + 1
890       if (ANY( ABS(pval(:))<ABS(val2) )) then
891         ipol = MINLOC(ABS(pval(:)),1)
892         ploc(ipol)=idx2; pval(ipol)=val2
893         write(std_out,*) ' pval:',pval
894         write(std_out,*) ' ploc:',ploc
895       end if
896     else if (((val1>val2).AND.(val2<val3))) then
897       if (sign(1.0_gwp,val2)>zero) CYCLE
898       ipoles = ipoles + 1
899       if (ANY( ABS(pval(:))<ABS(val2) )) then
900         ipol = MINLOC(ABS(pval(:)),1)
901         ploc(ipol)=idx2; pval(ipol)=val2
902         write(std_out,*) ' pval:',pval
903         write(std_out,*) ' ploc:',ploc
904       end if
905     end if
906   end do
907 ! Check last point
908   idx1 = nfreqre-2
909   idx2 = idx1 + 1
910 !  write(std_out,*) ' idx1:',idx1,' idx2:',idx2
911   val1 = AIMAG(fval(idx1))
912   val2 = AIMAG(fval(idx2))
913   if (ABS(val1)<ABS(val2)) then
914     ipoles = ipoles + 1
915     if (ANY( ABS(pval(:))<ABS(val2) )) then
916       ipol = MINLOC(ABS(pval(:)),1)
917       ploc(ipol)=idx2; pval(ipol)=val2
918        write(std_out,*) ' pval:',pval
919        write(std_out,*) ' ploc:',ploc
920     end if
921   end if
922   write(std_out,'(a,i0)') ' Number of poles real axis:',ipoles
923 
924 
925   ploc_prev = ploc; pval_prev = pval
926 
927 ! Do the rest of the imaginary grid until total
928 !  number of peaks found equals npoles or less
929   do iim=1,nfreqim-1
930     ploc=-1; pval=zero; ipol=1; ipoles=0
931     idx1 = nfreqre+iim
932     idx2 = nfreqre+nfreqim+1+(nfreqre-1)*(iim-1)
933 !    write(std_out,*) ' idx1:',idx1,' idx2:',idx2
934     val1 = AIMAG(fval(idx1))
935     val2 = AIMAG(fval(idx2))
936     if (ABS(val1)>ABS(val2)) then
937       ipoles = ipoles + 1
938       ploc(1)=idx1; pval(1)=val1
939       write(std_out,*) ' pval:',pval
940       write(std_out,*) ' ploc:',ploc
941     end if
942 !   Do all but the last
943     do ire=1,nfreqre-4
944        idx1 = nfreqre+nfreqim+1+(nfreqre-1)*(iim-1)+ire
945        idx2 = idx1+1
946        idx3 = idx1+2
947 !       write(std_out,*) ' idx1:',idx1,' idx2:',idx2,' idx3:',idx3
948        val1 = AIMAG(fval(idx1))
949        val2 = AIMAG(fval(idx2))
950        val3 = AIMAG(fval(idx3))
951        if (((val1<val2).AND.(val2>val3))) then
952          if (sign(1.0_gwp,val2)<zero) CYCLE
953          ipoles = ipoles + 1
954          if (ANY( ABS(pval(:))<ABS(val2) )) then
955            ipol = MINLOC(ABS(pval(:)),1)
956            ploc(ipol)=idx2; pval(ipol)=val2
957            write(std_out,*) ' pval:',pval
958            write(std_out,*) ' ploc:',ploc
959          end if
960        else if (((val1>val2).AND.(val2<val3))) then
961          if (sign(1.0_gwp,val2)>zero) CYCLE
962          ipoles = ipoles + 1
963          if (ANY( ABS(pval(:))<ABS(val2) )) then
964            ipol = MINLOC(ABS(pval(:)),1)
965            ploc(ipol)=idx2; pval(ipol)=val2
966            write(std_out,*) ' pval:',pval
967            write(std_out,*) ' ploc:',ploc
968          end if
969        end if
970     end do
971 !   Check last point
972     idx1 = nfreqre+nfreqim+1+(nfreqre-1)*(iim-1)+nfreqre-3
973     idx2 = idx1 + 1
974 !   write(std_out,*) ' idx1:',idx1,' idx2:',idx2
975     val1 = AIMAG(fval(idx1))
976     val2 = AIMAG(fval(idx2))
977     if (ABS(val1)<ABS(val2)) then
978       ipoles = ipoles + 1
979       if (ANY( ABS(pval(:))<ABS(val2) )) then
980         ipol = MINLOC(ABS(pval(:)),1)
981         ploc(ipol)=idx2; pval(ipol)=val2
982          write(std_out,*) ' pval:',pval
983          write(std_out,*) ' ploc:',ploc
984       end if
985     end if
986     write(std_out,'(2(a,i0))') ' Line,:',iim,' ipoles:',ipoles
987     if (ipoles<=npoles) then
988       iline = iim - 1
989       ploc = ploc_prev
990       EXIT
991     end if
992 
993     ploc_prev = ploc; pval_prev = pval
994 
995  end do
996 
997 end subroutine find_peaks

m_model_screening/im_screening [ Functions ]

[ Top ] [ m_model_screening ] [ Functions ]

NAME

  im_screening

FUNCTION

  Return the imaginary part of model dielectric / inverse dielectric
  function as given by a Drude-Lorentx model

  The function is a sum in the complex plane:
      f(z) = Sum_n  f_n * Im[ ((w_n^2-z^2) - i*gamma*z)^-1 ], z=a-i*b

  Here, f_n is the oscillator strength, w_n the location of the peak for
   the imaginary function, and gamma is related to the width

INPUTS

  omega      = (complex) Real and imaginary part of the frequency points
  coeff      = The coefficients in order: f_1,w_1,gamma_1,f_2,w_2,gamma_2,
                                          ...,f_n,w_n,gamma_n
  nomega     = number of fit points
  ncoeff     = number of coefficients

OUTPUT

NOTES

SOURCE

 80 subroutine im_screening(omega,fval,nomega,coeff,ncoeff)
 81 
 82   implicit none
 83 
 84 !Arguments ------------------------------------
 85 !scalars
 86   integer,intent(in)   :: nomega,ncoeff
 87 !arrays
 88   complex(dpc),intent(in)  :: omega(nomega)
 89   real(gwp)  ,intent(in)  :: coeff(ncoeff)
 90   real(gwp)  ,intent(out) :: fval(nomega)
 91 
 92 !Local variables-------------------------------
 93 !scalars
 94   integer :: io,ip
 95   real(gwp) :: rez,imz,realp,imagp
 96   real(gwp) :: fn,wn,gamman
 97 ! *********************************************************************
 98 
 99 ! The expression is: -f_n*(2*rez*imz-rez*gamma_n)
100 !    /( (-imz*gamma_n+w_n^2+imz^2-rez^2)^2 + (2*rez*imz-rez*gamma_n)^2 )
101 
102   do io=1,nomega
103     fval(io) = 0.0
104     rez =  REAL(omega(io))
105     imz = AIMAG(omega(io))
106     do ip=1,ncoeff,3
107       fn     = coeff(ip)
108       wn     = coeff(ip+1)
109       gamman = coeff(ip+2)
110       realp  = -imz*gamman+wn*wn+imz*imz-rez*rez
111       imagp  = rez*(two*imz-gamman)
112 
113         fval(io) = fval(io)-fn*imagp/((realp*realp)+(imagp*imagp))
114 
115     end do
116   end do
117 
118 end subroutine im_screening

m_model_screening/init_peaks_even_dist [ Functions ]

[ Top ] [ m_model_screening ] [ Functions ]

NAME

  init_peaks_even_dist

FUNCTION

  Distribute the peaks evenly along a line in the complex plane and
   normalise.

INPUTS

  omega      = (complex) Real and imaginary part of the frequency points
  yvals      = The function to be fitted in the complex plane
  coeff      = The coefficients in order: A_1,B_1,C_1,A_2,B_2,C_2,...,A_n,B_n,C_n
  nomega     = number of fit points
  ncoeff     = number of coefficients
  prtvol     = Verbosity of diagnostics

OUTPUT

NOTES

SOURCE

634 subroutine init_peaks_even_dist(omega,fval,nomega,nfreqre,coeff,ncoeff,prtvol)
635 
636   implicit none
637 
638 !Arguments ------------------------------------
639 !scalars
640   integer,intent(in)   :: nomega,nfreqre,ncoeff,prtvol
641 !arrays
642   complex(dpc) ,intent(in)  :: omega(nomega)
643   real(gwp)   ,intent(out) :: coeff(ncoeff)
644   complex(gwpc),intent(in)  :: fval(nomega)
645 
646 !Local variables-------------------------------
647 !scalars
648   integer :: npoles,ip,idx,iw
649   real(gwp) :: delta,norm,div,val1,val2,osc,pol,gam
650 
651 ! *********************************************************************
652 
653   npoles = ncoeff/3
654   div = real(npoles,gwp)
655 
656   delta = (omega(nfreqre)-omega(1))/(div+1.0_gwp)
657   ! Integrate function along real axis (trapezoid rule) and have normalised
658   ! oscillator strengths
659   norm = fval(1)*half
660   do iw=2,nfreqre-1
661     norm = norm + fval(iw)
662   end do
663   norm = norm + fval(nfreqre)*half
664   norm = norm*(omega(nfreqre)-omega(1))/real(nfreqre,gwp)
665   norm = norm/div
666 
667   do ip=1,npoles
668     idx = 3*(ip-1)+1
669     pol = delta*ip   ! Position of maximum
670     gam = 0.1_gwp ! Spread of function
671     val2 = gam*half
672     val1 = SQRT(pol*pol-val2*val2)
673     osc = norm*val1*two
674     coeff(idx  ) = osc!*(-1.0_gwp)**(ip-1)
675     coeff(idx+1) = pol   ! Position of maximum
676     coeff(idx+2) = -gam ! Spread of function
677     if (prtvol>9) then
678       write(std_out,'(a,a,i0)') ch10,' Pole no,: ',ip
679       write(std_out,'(a,ES16.8)')    '  Osc. strength:',osc
680       write(std_out,'(a,ES16.8,a)')  '  Peak location:',pol*Ha_eV,' eV'
681       write(std_out,'(a,ES16.8,a)')  '     Peak width:',gam*Ha_eV,' eV'
682       val2 = gam*half
683       val1 = SIGN(1.0_gwp,pol*pol-val2*val2)*SQRT(ABS(pol*pol-val2*val2))
684       write(std_out,'(a,ES16.8,a)')  ' Re[z] for pole:',val1*Ha_eV,' eV'
685       write(std_out,'(a,ES16.8,a)')  ' Im[z] for pole:',val2*Ha_eV,' eV'
686       write(std_out,'(a,ES16.8)')    '      Amplitude:',osc*half/ABS(val1)
687     end if
688   end do
689 
690 end subroutine init_peaks_even_dist

m_model_screening/init_peaks_from_grid [ Functions ]

[ Top ] [ m_model_screening ] [ Functions ]

NAME

  init_peaks_from_grid

FUNCTION

  Find an initial guess of coefficents from the "valleys" and "hills" in
   the complex plane.

INPUTS

  omega      = (complex) Real and imaginary part of the frequency points
  yvals      = The function to be fitted in the complex plane
  coeff      = The coefficients in order: A_1,B_1,C_1,A_2,B_2,C_2,...,A_n,B_n,C_n
  nomega     = number of fit points
  ncoeff     = number of coefficients
  prtvol   = Verbosity of diagnostics

OUTPUT

NOTES

SOURCE

446 subroutine init_peaks_from_grid(omega,fval,nomega,nfreqre,nfreqim,coeff,ncoeff,prtvol)
447 
448   implicit none
449 
450 !Arguments ------------------------------------
451 !scalars
452   integer,intent(in)   :: nomega,nfreqre,nfreqim,ncoeff,prtvol
453 !arrays
454   complex(dpc) ,intent(in)  :: omega(nomega)
455   real(gwp)   ,intent(out) :: coeff(ncoeff)
456   complex(gwpc),intent(in)  :: fval(nomega)
457 
458 !Local variables-------------------------------
459 !scalars
460   integer :: npoles,iline,idx,ip
461   real(gwp) :: pol,gam,maxv,df,dk,val2,b2,osc,val1
462   real(gwp) :: temp1,temp2,temp3
463 
464 !arrays
465   integer :: ploc(ncoeff/3)
466 
467 ! *********************************************************************
468 
469   npoles = ncoeff/3
470 
471 ! Map the evolution of peaks if prtvol>10
472   if (prtvol>10) then
473     call print_peaks(omega,fval,nomega,nfreqre,nfreqim)
474   end if ! prtvol>10
475 
476 ! Count the number of peaks per line and find the location of the
477 ! constant-imaginary frequency line wich has at least a number of
478 ! peaks commensurate with the requested number of poles
479   call find_peaks(fval,nomega,nfreqre,nfreqim,ploc,npoles,iline)
480   write(std_out,*) ' Optimum peak locations:',ploc
481   write(std_out,*) '               on iline:',iline
482 ! Now fit the peaks. A linear interpolation along the imaginary
483 !  direction is used to get a rough estimate of the width of
484 !  the peak.
485   do ip=1,npoles
486     pol  = REAL(omega(ploc(ip)))
487     maxv = AIMAG(fval(ploc(ip)))
488     write(std_out,*) ' maxv:',maxv
489     if (ploc(ip)<nfreqre+1) then ! We are right on the real axis
490       if (ploc(ip)==1) then ! Peak is at origin (Drude peak, i.e. metal)
491         b2   = AIMAG(omega(nfreqre+1))
492         val2 = AIMAG(fval(nfreqre+1))
493         write(std_out,*) '1: ploc:',ploc(ip),' b2:',b2,' val2:',val2
494       else ! Second value will be in c-plane
495         idx  = nfreqre+nfreqim+ploc(ip)-1
496         b2   = AIMAG(omega(idx))
497         val2 = AIMAG(fval(idx))
498         write(std_out,*) '2: ploc:',ploc(ip),' b2:',b2,' val2:',val2
499       end if
500     else if (ploc(ip)<nfreqre+nfreqim+1) then ! We are right on the imaginary axis
501       if (ploc(ip)==nfreqre+nfreqim) then
502         ABI_ERROR(' Peak in upper left corner. This should never happen')
503       end if
504       b2   = AIMAG(omega(ploc(ip)+1))
505       val2 = AIMAG(fval(ploc(ip)+1))
506         write(std_out,*) '3: ploc:',ploc(ip),' b2:',b2,' val2:',val2
507     else ! We are in the complex plane
508       idx  = ploc(ip)+nfreqre-1
509       b2   = AIMAG(omega(idx))
510       val2 = AIMAG(fval(idx))
511       write(std_out,*) '4: ploc:',ploc(ip),' idx:',idx,' b2:',b2,' val2:',val2
512     end if
513     df = ABS(val2 - maxv)
514     dk = df/b2
515     gam = -ABS(val2/dk)
516     !temp1 = SQRT(-b2*b2*val2*(val2+maxv)+(maxv*maxv)**2)
517     !temp2 = b2*(two*pol*pol+b2*b2)*val2-b2*maxv*pol*pol
518     !temp3 = (pol*pol+b2*b2)*val2+maxv*pol*pol
519     !gam = -((temp1-temp2)/temp3)
520     if (gam>zero) gam = ((temp1+temp2)/temp3)
521     osc = maxv*gam*pol
522     idx = 3*(ip-1)+1
523     coeff(idx  ) = osc ! Oscillator strength
524     coeff(idx+1) = pol ! Position of maximum
525     coeff(idx+2) = gam ! Spread of function
526     if (prtvol>9) then
527       write(std_out,'(a,a,i0)') ch10,' Pole no,: ',ip
528       write(std_out,'(a,ES16.8)')    '  Osc. strength:',osc
529       write(std_out,'(a,ES16.8,a)')  '  Peak location:',pol*Ha_eV,' eV'
530       write(std_out,'(a,ES16.8,a)')  '     Peak width:',gam*Ha_eV,' eV'
531       val2 = gam*half
532       val1 = SIGN(1.0_gwp,pol*pol-val2*val2)*SQRT(ABS(pol*pol-val2*val2))
533       write(std_out,'(a,ES16.8,a)')  ' Re[z] for pole:',val1*Ha_eV,' eV'
534       write(std_out,'(a,ES16.8,a)')  ' Im[z] for pole:',val2*Ha_eV,' eV'
535       write(std_out,'(a,ES16.8)')    '      Amplitude:',osc*half/ABS(val1)
536     end if
537   end do
538 
539 end subroutine init_peaks_from_grid

m_model_screening/init_single_peak [ Functions ]

[ Top ] [ m_model_screening ] [ Functions ]

NAME

  init_single_peak

FUNCTION

  Initialise a single peak by using the behaviour along the imaginary axis
   and the main peak

INPUTS

  omega      = (complex) Real and imaginary part of the frequency points
  yvals      = The function to be fitted in the complex plane
  coeff      = The coefficients in order: A_1,B_1,C_1,A_2,B_2,C_2,...,A_n,B_n,C_n
  nomega     = number of fit points
  ncoeff     = number of coefficients
  prtvol     = Verbosity of diagnostics

OUTPUT

NOTES

SOURCE

564 subroutine init_single_peak(omega,refval,imfval,nomega,nfreqre,coeff,prtvol)
565 
566   implicit none
567 
568 !Arguments ------------------------------------
569 !scalars
570   integer,intent(in)   :: nomega,nfreqre,prtvol
571 !arrays
572   complex(dpc),intent(in)  :: omega(nomega)
573   real(gwp)  ,intent(out) :: coeff(3)
574   real(gwp)  ,intent(in) :: refval(nomega),imfval(nomega)
575 
576 !Local variables-------------------------------
577 !scalars
578   integer :: maxpos,idx
579   real(gwp) :: pol,osc,gam,val1,val2,pol_sq
580 
581 ! *********************************************************************
582 
583   maxpos = MAXLOC(ABS(imfval(1:nfreqre)),1)
584   if (maxpos==1) maxpos = MAXLOC(ABS(imfval(2:nfreqre)),1)
585   pol = REAL(omega(maxpos))
586   pol_sq = pol*pol
587   osc = -refval(1)*pol_sq
588   idx = nfreqre+1
589   val2 = refval(idx)
590   val1 = osc+val2*pol_sq+val2*AIMAG(omega(idx))*AIMAG(omega(idx))
591   gam  = -ABS(val1/(AIMAG(omega(idx))*val2))
592 
593   coeff(1) = osc
594   coeff(2) = pol
595   coeff(3) = gam
596 
597   if (prtvol>9) then
598     write(std_out,'(a,ES16.8)')    '  Osc. strength:',osc
599     write(std_out,'(a,ES16.8,a)')  '  Peak location:',pol*Ha_eV,' eV'
600     write(std_out,'(a,ES16.8,a)')  '     Peak width:',gam*Ha_eV,' eV'
601     val2 = gam*half
602     val1 = SIGN(1.0_gwp,pol*pol-val2*val2)*SQRT(ABS(pol*pol-val2*val2))
603     write(std_out,'(a,ES16.8,a)')  ' Re[z] for pole:',val1*Ha_eV,' eV'
604     write(std_out,'(a,ES16.8,a)')  ' Im[z] for pole:',val2*Ha_eV,' eV'
605     write(std_out,'(a,ES16.8)')    '      Amplitude:',osc*half/ABS(val1)
606   end if
607 
608 end subroutine init_single_peak

m_model_screening/print_peaks [ Functions ]

[ Top ] [ m_model_screening ] [ Functions ]

NAME

  print_peaks

FUNCTION

  Find and output the location of peaks on the grid in a file

INPUTS

  omega      = (complex) Real and imaginary part of the frequency points
  fvals      = The function to be fitted in the complex plane
  nomega     = number of fit points
  nfreqre    = number or imaginary gridlines
  nfreqim    = number of real gridlines

OUTPUT

NOTES

SOURCE

714 subroutine print_peaks(omega,fval,nomega,nfreqre,nfreqim)
715 
716  implicit none
717 
718 !Arguments ------------------------------------
719 !scalars
720   integer,intent(in)   :: nomega,nfreqre,nfreqim
721 !arrays
722   complex(dpc) ,intent(in)  :: omega(nomega)
723   complex(gwpc),intent(in)  :: fval(nomega)
724 
725 !Local variables-------------------------------
726 !scalars
727   integer :: ire,iim,unt_tmp
728   integer :: idx1,idx2,idx3
729   real(gwp) :: rez,imz,val1,val2,val3
730   character(len=500) :: msg
731 
732 ! *********************************************************************
733 
734   if (open_file("grid_peak_tree.dat", msg, newunit=unt_tmp) /= 0) then
735     ABI_ERROR(msg)
736   end if
737 
738   do iim=nfreqim,1,-1
739 !    write(std_out,*) ' iim:',iim
740 !   Check first points
741     idx1 = nfreqre+iim
742     idx2 = nfreqre+nfreqim+1+(nfreqre-1)*(iim-1)
743 !    write(std_out,*) ' idx1:',idx1,' idx2:',idx2
744     val1 = AIMAG(fval(idx1))
745     val2 = AIMAG(fval(idx2))
746     if (ABS(val1)>ABS(val2)) then
747       rez = REAL(omega(idx1))
748       imz = AIMAG(omega(idx1))
749       write(unt_tmp,'(2f8.2,4x,ES16.8)') rez*Ha_eV,imz*Ha_eV,val1
750     end if
751 !   Do all but the last
752     do ire=1,nfreqre-4
753        idx1 = nfreqre+nfreqim+1+(nfreqre-1)*(iim-1)+ire
754        idx2 = idx1+1
755        idx3 = idx1+2
756 !       write(std_out,*) ' idx1:',idx1,' idx2:',idx2,' idx3:',idx3
757        rez = REAL(omega(idx2))
758        imz = AIMAG(omega(idx2))
759        val1 = AIMAG(fval(idx1))
760        val2 = AIMAG(fval(idx2))
761        val3 = AIMAG(fval(idx3))
762        if (((val1<val2).AND.(val2>val3))) then
763          if (sign(1.0_gwp,val2)<zero) CYCLE
764          write(unt_tmp,'(2f8.2,4x,ES16.8)') rez*Ha_eV,imz*Ha_eV,val2
765        else if (((val1>val2).AND.(val2<val3))) then
766          if (sign(1.0_gwp,val2)>zero) CYCLE
767          write(unt_tmp,'(2f8.2,4x,ES16.8)') rez*Ha_eV,imz*Ha_eV,val2
768        end if
769     end do
770 !   Check last point
771     idx1 = nfreqre+nfreqim+1+(nfreqre-1)*(iim-1)+nfreqre-3
772     idx2 = idx1 + 1
773 !   write(std_out,*) ' idx1:',idx1,' idx2:',idx2
774     rez = REAL(omega(idx2))
775     imz = AIMAG(omega(idx2))
776     val1 = AIMAG(fval(idx1))
777     val2 = AIMAG(fval(idx2))
778     if (ABS(val1)<ABS(val2)) then
779       write(unt_tmp,'(2f8.2,4x,ES16.8)') rez*Ha_eV,imz*Ha_eV,val2
780     end if
781   end do
782 ! finally, do the purely real axis
783 ! Check first points
784   idx1 = 1; idx2 = 2
785   val1 = AIMAG(fval(idx1)); val2 = AIMAG(fval(idx2))
786   if (ABS(val1)>ABS(val2)) then
787     rez = REAL(omega(idx1))
788     imz = AIMAG(omega(idx1))
789     write(unt_tmp,'(2f8.2,4x,ES16.8)') rez*Ha_eV,imz*Ha_eV,val1
790   end if
791   do ire=2,nfreqre-3
792     idx1 = ire; idx2 = idx1+1; idx3 = idx1+2
793     rez = REAL(omega(idx2))
794     imz = AIMAG(omega(idx2))
795     val1 = AIMAG(fval(idx1))
796     val2 = AIMAG(fval(idx2))
797     val3 = AIMAG(fval(idx3))
798     if (((val1<val2).AND.(val2>val3))) then
799       if (sign(1.0_gwp,val2)<zero) CYCLE
800       write(unt_tmp,'(2f8.2,4x,ES16.8)') rez*Ha_eV,imz*Ha_eV,val2
801     else if (((val1>val2).AND.(val2<val3))) then
802       if (sign(1.0_gwp,val2)>zero) CYCLE
803       write(unt_tmp,'(2f8.2,4x,ES16.8)') rez*Ha_eV,imz*Ha_eV,val2
804     end if
805   end do
806 ! Check last point
807   idx1 = nfreqre-2
808   idx2 = idx1 + 1
809 !  write(std_out,*) ' idx1:',idx1,' idx2:',idx2
810   rez = REAL(omega(idx2))
811   imz = AIMAG(omega(idx2))
812   val1 = AIMAG(fval(idx1))
813   val2 = AIMAG(fval(idx2))
814   if (ABS(val1)<ABS(val2)) then
815     write(unt_tmp,'(2f8.2,4x,ES16.8)') rez*Ha_eV,imz*Ha_eV,val2
816   end if
817 
818   close(unt_tmp)
819 
820 end subroutine print_peaks

m_model_screening/re_and_im_screening [ Functions ]

[ Top ] [ m_model_screening ] [ Functions ]

NAME

  re_and_im_screening

FUNCTION

  Return the real and imaginary part of model dielectric / inverse dielectric
  function as evaluated from pole coefficients.

  The function is a sum of poles in the complex plane:
      f(z) = Sum_n[ A/(z-(B-iC)) - A/(z-(-B+iC)) ],
   where each pole occurs twice in a time-ordered fashion.

  Here, the A are the oscillator strengths, B the real component of the position
  of the pole, and C the imaginary component.

INPUTS

  omega      = (complex) Real and imaginary part of the frequency points
  coeff      = The coefficients in order: A_1,B_1,C_1,A_2,B_2,C_2,...,A_n,B_n,C_n
  nomega     = number of fit points
  ncoeff     = number of coefficients

OUTPUT

NOTES

SOURCE

216 subroutine re_and_im_screening(omega,fval,nomega,coeff,ncoeff)
217 
218   implicit none
219 
220 !Arguments ------------------------------------
221 !scalars
222   integer,intent(in)   :: nomega,ncoeff
223 !arrays
224   complex(dpc) ,intent(in)  :: omega(nomega)
225   real(gwp)   ,intent(in)  :: coeff(ncoeff)
226   complex(gwp),intent(out) :: fval(nomega)
227 
228 !Local variables-------------------------------
229 !scalars
230   integer :: io,ip
231   real(gwp) :: rez,imz,realp,imagp,refval,imfval
232   real(gwp) :: fn,wn,gamman
233 ! *********************************************************************
234 
235 ! The expression is: fn*(-imz*gamma+w_n^2+imz^2-rez^2)
236 !    /( (-imz*gamma+w_n^2+imz^2-rez^2)^2 + (2*rez*imz-rez*gamma)^2 )
237 
238   do io=1,nomega
239     fval(io) = 0.0
240     rez =  REAL(omega(io))
241     imz = AIMAG(omega(io))
242     do ip=1,ncoeff,3
243       fn     = coeff(ip)
244       wn     = coeff(ip+1)
245       gamman = coeff(ip+2)
246       realp  = -imz*gamman+wn*wn+imz*imz-rez*rez
247       imagp  = rez*(two*imz-gamman)
248 
249         refval   = fn*realp/((realp*realp)+(imagp*imagp))
250         imfval   = fn*imagp/((realp*realp)+(imagp*imagp))
251 
252         fval(io) = fval(io)-CMPLX(refval,imfval)
253 
254     end do
255   end do
256 
257 end subroutine re_and_im_screening

m_model_screening/re_and_im_screening_with_phase [ Functions ]

[ Top ] [ m_model_screening ] [ Functions ]

NAME

  re_and_im_screening_with_phase

FUNCTION

  Return the real and imaginary part of model dielectric / inverse dielectric
  function as evaluated from pole coefficients.

  The function is a sum of poles in the complex plane:
      f(z) = Sum_n[ A/(z-(B-iC)) - A/(z-(-B+iC)) ],
   where each pole occurs twice in a time-ordered fashion.

  Here, the A are the oscillator strengths, B the real component of the position
  of the pole, and C the imaginary component.

INPUTS

  omega      = (complex) Real and imaginary part of the frequency points
  coeff      = The coefficients in order: A_1,B_1,C_1,A_2,B_2,C_2,...,A_n,B_n,C_n
  nomega     = number of fit points
  ncoeff     = number of coefficients

OUTPUT

NOTES

SOURCE

287 subroutine re_and_im_screening_with_phase(omega,fval,nomega,coeff,ncoeff)
288 
289   implicit none
290 
291 !Arguments ------------------------------------
292 !scalars
293   integer,intent(in)   :: nomega,ncoeff
294 !arrays
295   complex(dpc) ,intent(in)  :: omega(nomega)
296   real(gwp)   ,intent(in)  :: coeff(ncoeff)
297   complex(gwpc),intent(out) :: fval(nomega)
298 
299 !Local variables-------------------------------
300 !scalars
301   integer :: io,ip,npoles
302   real(gwp) :: rez,imz,realp,imagp,refval,imfval,retemp,imtemp
303   real(gwp) :: fn,wn,gamman,imrot,rerot
304 ! *********************************************************************
305 
306 ! The expression is: fn*(-imz*gamma+w_n^2+imz^2-rez^2)
307 !    /( (-imz*gamma+w_n^2+imz^2-rez^2)^2 + (2*rez*imz-rez*gamma)^2 )
308   npoles = (ncoeff-1)/3
309 
310   do io=1,nomega
311     fval(io) = 0.0
312     rez =  REAL(omega(io))
313     imz = AIMAG(omega(io))
314     do ip=1,(ncoeff-1),3
315       fn     = coeff(ip)
316       wn     = coeff(ip+1)
317       gamman = coeff(ip+2)
318       realp  = -imz*gamman+wn*wn+imz*imz-rez*rez
319       imagp  = rez*(two*imz-gamman)
320 
321         refval   = fn*realp/((realp*realp)+(imagp*imagp))
322         imfval   = fn*imagp/((realp*realp)+(imagp*imagp))
323 
324         fval(io) = fval(io)-CMPLX(refval,imfval)
325 
326     end do
327     ! Restore phase
328     rerot = COS(coeff(npoles*3+1))
329     imrot = SIN(coeff(npoles*3+1))
330     retemp = REAL(fval(io))
331     imtemp = AIMAG(fval(io))
332     fval(io) = CMPLX(rerot*retemp-imrot*imtemp,rerot*imtemp + imrot*retemp)
333   end do
334 
335 end subroutine re_and_im_screening_with_phase

m_model_screening/re_screening [ Functions ]

[ Top ] [ m_model_screening ] [ Functions ]

NAME

  re_screening

FUNCTION

  Return the real part of model dielectric / inverse dielectric
  function as evaluated from pole coefficients.

  The function is a sum of poles in the complex plane:
      f(z) = Sum_n[ A/(z-(B-iC)) - A/(z-(-B+iC)) ],
   where each pole occurs twice in a time-ordered fashion.

  Here, the A are the oscillator strengths, B the real component of the position
  of the pole, and C the imaginary component.

INPUTS

  omega      = (complex) Real and imaginary part of the frequency points
  coeff      = The coefficients in order: A_1,B_1,C_1,A_2,B_2,C_2,...,A_n,B_n,C_n
  nomega     = number of fit points
  ncoeff     = number of coefficients

OUTPUT

NOTES

SOURCE

148 subroutine re_screening(omega,fval,nomega,coeff,ncoeff)
149 
150   implicit none
151 
152 !Arguments ------------------------------------
153 !scalars
154   integer,intent(in)   :: nomega,ncoeff
155 !arrays
156   complex(dpc),intent(in)  :: omega(nomega)
157   real(gwp)  ,intent(in)  :: coeff(ncoeff)
158   real(gwp)  ,intent(out) :: fval(nomega)
159 
160 !Local variables-------------------------------
161 !scalars
162   integer :: io,ip
163   real(gwp) :: rez,imz,realp,imagp
164   real(gwp) :: fn,wn,gamman
165 ! *********************************************************************
166 
167 ! The expression is: fn*(-imz*gamma+w_n^2+imz^2-rez^2)
168 !    /( (-imz*gamma+w_n^2+imz^2-rez^2)^2 + (2*rez*imz-rez*gamma)^2 )
169 
170   do io=1,nomega
171     fval(io) = 0.0
172     rez =  REAL(omega(io))
173     imz = AIMAG(omega(io))
174     do ip=1,ncoeff,3
175       fn     = coeff(ip)
176       wn     = coeff(ip+1)
177       gamman = coeff(ip+2)
178       realp  = -imz*gamman+wn*wn+imz*imz-rez*rez
179       imagp  = rez*(two*imz-gamman)
180 
181         fval(io) = fval(io)-fn*realp/((realp*realp)+(imagp*imagp))
182 
183     end do
184   end do
185 
186 end subroutine re_screening

m_model_screening/remove_phase [ Functions ]

[ Top ] [ m_model_screening ] [ Functions ]

NAME

  remove_phase

FUNCTION

  Find out what the complex phase factor is for off-diagonal elements
   and unmix the components.

INPUTS

  fvals  = The function to be fitted in the complex plane.
  nomega = Number of fit points.
  nfreqre    = number or imaginary gridlines
  phase  = The phase angle.

OUTPUT

NOTES

SOURCE

1020 subroutine remove_phase(fval,nomega,phase)
1021 
1022   implicit none
1023 
1024 !Arguments ------------------------------------
1025 !scalars
1026   integer,    intent(in)  :: nomega
1027   real(gwp), intent(out) :: phase
1028 !arrays
1029   complex(gwpc), intent(inout) :: fval(nomega)
1030 
1031 !Local variables-------------------------------
1032 !scalars
1033   integer       :: io
1034   real(gwp)    :: a,b,retemp,imtemp
1035 
1036 ! *********************************************************************
1037 
1038 ! The phase can be found by checking when the function is
1039 !  identically zero along the imaginary axis
1040   if (ABS(AIMAG(fval(1)))<tol14) then ! Phase is zero
1041     phase = zero
1042     RETURN
1043   else if (ABS(REAL(fval(1)))<tol14) then ! Phase is exactly pi/2
1044     phase = pi*half
1045     a = zero
1046     b = -1.0_gwp
1047   else
1048     phase = ATAN(AIMAG(fval(1))/REAL(fval(1)))
1049     a = COS(phase)
1050     b = -SIN(phase)
1051   end if
1052 ! Rotate values
1053   do io=1,nomega
1054     retemp = REAL(fval(io))
1055     imtemp = AIMAG(fval(io))
1056     fval(io) = CMPLX(a*retemp-b*imtemp,a*imtemp+b*retemp)
1057   end do
1058 
1059 end subroutine remove_phase

m_model_screening/sequential_fitting [ Functions ]

[ Top ] [ m_model_screening ] [ Functions ]

NAME

  sequential_fitting

FUNCTION

  Fit a function in the complex plane pole-by-pole in such
  a way as to increasingly minimise the error

INPUTS

  omega      = (complex) Real and imaginary part of the frequency points
  refval     = Real part of function to be fitted
  imfval     = imaginary part of function to be fitted
  nomega     = Total number of points in the complex plane
  nfreqre    = Number of points along real axis
  nfreqim    = Number of points along imaginary axis
  coeff      = The coefficients in order: A_1,B_1,C_1,A_2,B_2,C_2,...,A_n,B_n,C_n
  ncoeff     = number of coefficients
  prtvol     = Diagnostics verbose level

OUTPUT

NOTES

SOURCE

364 subroutine sequential_fitting(omega,refval,imfval,nomega,nfreqre,coeff,&
365 & ncoeff,prtvol,startcoeff)
366 
367   implicit none
368 
369 !Arguments ------------------------------------
370 !scalars
371   integer,intent(in)   :: nomega,nfreqre,ncoeff,prtvol
372 !arrays
373   complex(dpc),intent(in)     :: omega(nomega)
374   real(gwp)  ,intent(out)    :: coeff(ncoeff)
375   real(gwp)  ,intent(inout)  :: refval(nomega),imfval(nomega)
376   real(gwp),optional,intent(out) :: startcoeff(ncoeff)
377 
378 !Local variables-------------------------------
379 !scalars
380   integer :: ip,npoles,idx
381   real(gwp) :: thiscoeff(3),norm,invnorm
382   real(dpc)  :: re_zvals(nomega),im_zvals(nomega)
383 !  real(dpc)  :: orig_refval(nomega),orig_imfval(nomega)
384   complex(gwp) :: pole_func(nomega)
385 ! *********************************************************************
386 
387   npoles = ncoeff/3
388   re_zvals(:) = REAL(omega(:))
389   im_zvals(:) = AIMAG(omega(:))
390 
391   ! Normalise
392   norm    = MAXVAL(ABS(imfval))
393   invnorm = 1.0_gwp/norm
394   refval  = invnorm*refval
395   imfval  = invnorm*imfval
396 
397   ! Loop over poles to fit
398   do ip=1,npoles
399     idx = 3*(ip-1)+1
400     ! Initialise pole
401     call init_single_peak(omega,refval,imfval,nomega,nfreqre,thiscoeff,prtvol)
402     if (present(startcoeff)) then
403       startcoeff(idx:idx+2) = thiscoeff(1:3)
404     end if
405     ! Make fit
406 #ifdef HAVE_LEVMAR
407     call dfit_re_and_im_screening(re_zvals,im_zvals,imfval,refval,&
408 &    nomega,3,thiscoeff,prtvol)
409 #else
410     ABI_ERROR(' ABINIT was not compiled with the levmar library!')
411 #endif
412     ! Remove current fit
413     call re_and_im_screening(omega,pole_func,nomega,thiscoeff,3)
414     refval(:) = refval(:) -  REAL(pole_func(:))
415     imfval(:) = imfval(:) - AIMAG(pole_func(:))
416     coeff(idx:idx+2) = thiscoeff(1:3)
417     coeff(idx) = norm*coeff(idx)
418   end do
419 
420 end subroutine sequential_fitting