LCOV - code coverage report
Current view: top level - src/70_gw - m_model_screening.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 365 0
Test Date: 2026-09-20 18:56:22 Functions: 0.0 % 11 0

            Line data    Source code
       1              : !!****m* ABINIT/m_model_screening
       2              : !! NAME
       3              : !! m_model_screening
       4              : !!
       5              : !! FUNCTION
       6              : !!  Module containing functions for calculating and fitting model dielectric functions
       7              : !!
       8              : !! COPYRIGHT
       9              : !!  Copyright (C) 2008-2026 ABINIT group (MS)
      10              : !!  This file is distributed under the terms of the
      11              : !!  GNU General Public License, see ~abinit/COPYING
      12              : !!  or http://www.gnu.org/copyleft/gpl.txt .
      13              : !!
      14              : !! SOURCE
      15              : 
      16              : #if defined HAVE_CONFIG_H
      17              : #include "config.h"
      18              : #endif
      19              : 
      20              : #include "abi_common.h"
      21              : 
      22              : MODULE m_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  !==============================================================================
      51              : !!***
      52              : 
      53              : !!****f* m_model_screening/im_screening
      54              : !! NAME
      55              : !!  im_screening
      56              : !!
      57              : !! FUNCTION
      58              : !!  Return the imaginary part of model dielectric / inverse dielectric
      59              : !!  function as given by a Drude-Lorentx model
      60              : !!
      61              : !!  The function is a sum in the complex plane:
      62              : !!      f(z) = Sum_n  f_n * Im[ ((w_n^2-z^2) - i*gamma*z)^-1 ], z=a-i*b
      63              : !!
      64              : !!  Here, f_n is the oscillator strength, w_n the location of the peak for
      65              : !!   the imaginary function, and gamma is related to the width
      66              : !!
      67              : !! INPUTS
      68              : !!  omega      = (complex) Real and imaginary part of the frequency points
      69              : !!  coeff      = The coefficients in order: f_1,w_1,gamma_1,f_2,w_2,gamma_2,
      70              : !!                                          ...,f_n,w_n,gamma_n
      71              : !!  nomega     = number of fit points
      72              : !!  ncoeff     = number of coefficients
      73              : !!
      74              : !! OUTPUT
      75              : !!
      76              : !! NOTES
      77              : !!
      78              : !! SOURCE
      79              : 
      80            0 : subroutine im_screening(omega,fval,nomega,coeff,ncoeff)
      81              : 
      82              : !Arguments ------------------------------------
      83              : !scalars
      84              :   integer,intent(in)   :: nomega,ncoeff
      85              : !arrays
      86              :   complex(dp),intent(in)  :: omega(nomega)
      87              :   real(gwp)  ,intent(in)  :: coeff(ncoeff)
      88              :   real(gwp)  ,intent(out) :: fval(nomega)
      89              : 
      90              : !Local variables-------------------------------
      91              : !scalars
      92              :   integer :: io,ip
      93              :   real(gwp) :: rez,imz,realp,imagp
      94              :   real(gwp) :: fn,wn,gamman
      95              : ! *********************************************************************
      96              : 
      97              : ! The expression is: -f_n*(2*rez*imz-rez*gamma_n)
      98              : !    /( (-imz*gamma_n+w_n^2+imz^2-rez^2)^2 + (2*rez*imz-rez*gamma_n)^2 )
      99              : 
     100            0 :   do io=1,nomega
     101            0 :     fval(io) = 0.0
     102            0 :     rez =  REAL(omega(io))
     103            0 :     imz = AIMAG(omega(io))
     104            0 :     do ip=1,ncoeff,3
     105            0 :       fn     = coeff(ip)
     106            0 :       wn     = coeff(ip+1)
     107            0 :       gamman = coeff(ip+2)
     108            0 :       realp  = -imz*gamman+wn*wn+imz*imz-rez*rez
     109            0 :       imagp  = rez*(two*imz-gamman)
     110              : 
     111            0 :         fval(io) = fval(io)-fn*imagp/((realp*realp)+(imagp*imagp))
     112              : 
     113              :     end do
     114              :   end do
     115              : 
     116            0 : end subroutine im_screening
     117              : !!***
     118              : 
     119              : !!****f* m_model_screening/re_screening
     120              : !! NAME
     121              : !!  re_screening
     122              : !!
     123              : !! FUNCTION
     124              : !!  Return the real part of model dielectric / inverse dielectric
     125              : !!  function as evaluated from pole coefficients.
     126              : !!
     127              : !!  The function is a sum of poles in the complex plane:
     128              : !!      f(z) = Sum_n[ A/(z-(B-iC)) - A/(z-(-B+iC)) ],
     129              : !!   where each pole occurs twice in a time-ordered fashion.
     130              : !!
     131              : !!  Here, the A are the oscillator strengths, B the real component of the position
     132              : !!  of the pole, and C the imaginary component.
     133              : !!
     134              : !! INPUTS
     135              : !!  omega      = (complex) Real and imaginary part of the frequency points
     136              : !!  coeff      = The coefficients in order: A_1,B_1,C_1,A_2,B_2,C_2,...,A_n,B_n,C_n
     137              : !!  nomega     = number of fit points
     138              : !!  ncoeff     = number of coefficients
     139              : !!
     140              : !! OUTPUT
     141              : !!
     142              : !! NOTES
     143              : !!
     144              : !! SOURCE
     145              : 
     146            0 : subroutine re_screening(omega,fval,nomega,coeff,ncoeff)
     147              : 
     148              : !Arguments ------------------------------------
     149              : !scalars
     150              :   integer,intent(in)   :: nomega,ncoeff
     151              : !arrays
     152              :   complex(dp),intent(in)  :: omega(nomega)
     153              :   real(gwp)  ,intent(in)  :: coeff(ncoeff)
     154              :   real(gwp)  ,intent(out) :: fval(nomega)
     155              : 
     156              : !Local variables-------------------------------
     157              : !scalars
     158              :   integer :: io,ip
     159              :   real(gwp) :: rez,imz,realp,imagp
     160              :   real(gwp) :: fn,wn,gamman
     161              : ! *********************************************************************
     162              : 
     163              : ! The expression is: fn*(-imz*gamma+w_n^2+imz^2-rez^2)
     164              : !    /( (-imz*gamma+w_n^2+imz^2-rez^2)^2 + (2*rez*imz-rez*gamma)^2 )
     165              : 
     166            0 :   do io=1,nomega
     167            0 :     fval(io) = 0.0
     168            0 :     rez =  REAL(omega(io))
     169            0 :     imz = AIMAG(omega(io))
     170            0 :     do ip=1,ncoeff,3
     171            0 :       fn     = coeff(ip)
     172            0 :       wn     = coeff(ip+1)
     173            0 :       gamman = coeff(ip+2)
     174            0 :       realp  = -imz*gamman+wn*wn+imz*imz-rez*rez
     175            0 :       imagp  = rez*(two*imz-gamman)
     176              : 
     177            0 :         fval(io) = fval(io)-fn*realp/((realp*realp)+(imagp*imagp))
     178              : 
     179              :     end do
     180              :   end do
     181              : 
     182            0 : end subroutine re_screening
     183              : !!***
     184              : 
     185              : !!****f* m_model_screening/re_and_im_screening
     186              : !! NAME
     187              : !!  re_and_im_screening
     188              : !!
     189              : !! FUNCTION
     190              : !!  Return the real and imaginary part of model dielectric / inverse dielectric
     191              : !!  function as evaluated from pole coefficients.
     192              : !!
     193              : !!  The function is a sum of poles in the complex plane:
     194              : !!      f(z) = Sum_n[ A/(z-(B-iC)) - A/(z-(-B+iC)) ],
     195              : !!   where each pole occurs twice in a time-ordered fashion.
     196              : !!
     197              : !!  Here, the A are the oscillator strengths, B the real component of the position
     198              : !!  of the pole, and C the imaginary component.
     199              : !!
     200              : !! INPUTS
     201              : !!  omega      = (complex) Real and imaginary part of the frequency points
     202              : !!  coeff      = The coefficients in order: A_1,B_1,C_1,A_2,B_2,C_2,...,A_n,B_n,C_n
     203              : !!  nomega     = number of fit points
     204              : !!  ncoeff     = number of coefficients
     205              : !!
     206              : !! OUTPUT
     207              : !!
     208              : !! NOTES
     209              : !!
     210              : !! SOURCE
     211              : 
     212            0 : subroutine re_and_im_screening(omega,fval,nomega,coeff,ncoeff)
     213              : 
     214              : !Arguments ------------------------------------
     215              : !scalars
     216              :   integer,intent(in)   :: nomega,ncoeff
     217              : !arrays
     218              :   complex(dp) ,intent(in)  :: omega(nomega)
     219              :   real(gwp)   ,intent(in)  :: coeff(ncoeff)
     220              :   complex(gwp),intent(out) :: fval(nomega)
     221              : 
     222              : !Local variables-------------------------------
     223              : !scalars
     224              :   integer :: io,ip
     225              :   real(gwp) :: rez,imz,realp,imagp,refval,imfval
     226              :   real(gwp) :: fn,wn,gamman
     227              : ! *********************************************************************
     228              : 
     229              : ! The expression is: fn*(-imz*gamma+w_n^2+imz^2-rez^2)
     230              : !    /( (-imz*gamma+w_n^2+imz^2-rez^2)^2 + (2*rez*imz-rez*gamma)^2 )
     231              : 
     232            0 :   do io=1,nomega
     233            0 :     fval(io) = 0.0
     234            0 :     rez =  REAL(omega(io))
     235            0 :     imz = AIMAG(omega(io))
     236            0 :     do ip=1,ncoeff,3
     237            0 :       fn     = coeff(ip)
     238            0 :       wn     = coeff(ip+1)
     239            0 :       gamman = coeff(ip+2)
     240            0 :       realp  = -imz*gamman+wn*wn+imz*imz-rez*rez
     241            0 :       imagp  = rez*(two*imz-gamman)
     242              : 
     243            0 :         refval   = fn*realp/((realp*realp)+(imagp*imagp))
     244            0 :         imfval   = fn*imagp/((realp*realp)+(imagp*imagp))
     245              : 
     246            0 :         fval(io) = fval(io)-CMPLX(refval,imfval)
     247              : 
     248              :     end do
     249              :   end do
     250              : 
     251            0 : end subroutine re_and_im_screening
     252              : !!***
     253              : 
     254              : !!****f* m_model_screening/re_and_im_screening_with_phase
     255              : !! NAME
     256              : !!  re_and_im_screening_with_phase
     257              : !!
     258              : !! FUNCTION
     259              : !!  Return the real and imaginary part of model dielectric / inverse dielectric
     260              : !!  function as evaluated from pole coefficients.
     261              : !!
     262              : !!  The function is a sum of poles in the complex plane:
     263              : !!      f(z) = Sum_n[ A/(z-(B-iC)) - A/(z-(-B+iC)) ],
     264              : !!   where each pole occurs twice in a time-ordered fashion.
     265              : !!
     266              : !!  Here, the A are the oscillator strengths, B the real component of the position
     267              : !!  of the pole, and C the imaginary component.
     268              : !!
     269              : !! INPUTS
     270              : !!  omega      = (complex) Real and imaginary part of the frequency points
     271              : !!  coeff      = The coefficients in order: A_1,B_1,C_1,A_2,B_2,C_2,...,A_n,B_n,C_n
     272              : !!  nomega     = number of fit points
     273              : !!  ncoeff     = number of coefficients
     274              : !!
     275              : !! OUTPUT
     276              : !!
     277              : !! NOTES
     278              : !!
     279              : !! SOURCE
     280              : 
     281            0 : subroutine re_and_im_screening_with_phase(omega,fval,nomega,coeff,ncoeff)
     282              : 
     283              : !Arguments ------------------------------------
     284              : !scalars
     285              :   integer,intent(in)   :: nomega,ncoeff
     286              : !arrays
     287              :   complex(dp) ,intent(in)  :: omega(nomega)
     288              :   real(gwp)   ,intent(in)  :: coeff(ncoeff)
     289              :   complex(gwp),intent(out) :: fval(nomega)
     290              : 
     291              : !Local variables-------------------------------
     292              : !scalars
     293              :   integer :: io,ip,npoles
     294              :   real(gwp) :: rez,imz,realp,imagp,refval,imfval,retemp,imtemp
     295              :   real(gwp) :: fn,wn,gamman,imrot,rerot
     296              : ! *********************************************************************
     297              : 
     298              : ! The expression is: fn*(-imz*gamma+w_n^2+imz^2-rez^2)
     299              : !    /( (-imz*gamma+w_n^2+imz^2-rez^2)^2 + (2*rez*imz-rez*gamma)^2 )
     300            0 :   npoles = (ncoeff-1)/3
     301              : 
     302            0 :   do io=1,nomega
     303            0 :     fval(io) = 0.0
     304            0 :     rez =  REAL(omega(io))
     305            0 :     imz = AIMAG(omega(io))
     306            0 :     do ip=1,(ncoeff-1),3
     307            0 :       fn     = coeff(ip)
     308            0 :       wn     = coeff(ip+1)
     309            0 :       gamman = coeff(ip+2)
     310            0 :       realp  = -imz*gamman+wn*wn+imz*imz-rez*rez
     311            0 :       imagp  = rez*(two*imz-gamman)
     312              : 
     313            0 :         refval   = fn*realp/((realp*realp)+(imagp*imagp))
     314            0 :         imfval   = fn*imagp/((realp*realp)+(imagp*imagp))
     315              : 
     316            0 :         fval(io) = fval(io)-CMPLX(refval,imfval)
     317              : 
     318              :     end do
     319              :     ! Restore phase
     320            0 :     rerot = COS(coeff(npoles*3+1))
     321            0 :     imrot = SIN(coeff(npoles*3+1))
     322            0 :     retemp = REAL(fval(io))
     323            0 :     imtemp = AIMAG(fval(io))
     324            0 :     fval(io) = CMPLX(rerot*retemp-imrot*imtemp,rerot*imtemp + imrot*retemp)
     325              :   end do
     326              : 
     327            0 : end subroutine re_and_im_screening_with_phase
     328              : !!***
     329              : 
     330              : 
     331              : !!****f* m_model_screening/sequential_fitting
     332              : !! NAME
     333              : !!  sequential_fitting
     334              : !!
     335              : !! FUNCTION
     336              : !!  Fit a function in the complex plane pole-by-pole in such
     337              : !!  a way as to increasingly minimise the error
     338              : !!
     339              : !! INPUTS
     340              : !!  omega      = (complex) Real and imaginary part of the frequency points
     341              : !!  refval     = Real part of function to be fitted
     342              : !!  imfval     = imaginary part of function to be fitted
     343              : !!  nomega     = Total number of points in the complex plane
     344              : !!  nfreqre    = Number of points along real axis
     345              : !!  nfreqim    = Number of points along imaginary axis
     346              : !!  coeff      = The coefficients in order: A_1,B_1,C_1,A_2,B_2,C_2,...,A_n,B_n,C_n
     347              : !!  ncoeff     = number of coefficients
     348              : !!  prtvol     = Diagnostics verbose level
     349              : !!
     350              : !! OUTPUT
     351              : !!
     352              : !! NOTES
     353              : !!
     354              : !! SOURCE
     355              : 
     356            0 : subroutine sequential_fitting(omega,refval,imfval,nomega,nfreqre,coeff,&
     357              : & ncoeff,prtvol,startcoeff)
     358              : 
     359              : !Arguments ------------------------------------
     360              : !scalars
     361              :   integer,intent(in)   :: nomega,nfreqre,ncoeff,prtvol
     362              : !arrays
     363              :   complex(dp),intent(in)     :: omega(nomega)
     364              :   real(gwp)  ,intent(out)    :: coeff(ncoeff)
     365              :   real(gwp)  ,intent(inout)  :: refval(nomega),imfval(nomega)
     366              :   real(gwp),optional,intent(out) :: startcoeff(ncoeff)
     367              : 
     368              : !Local variables-------------------------------
     369              : !scalars
     370              :   integer :: ip,npoles,idx
     371              :   real(gwp) :: thiscoeff(3),norm,invnorm
     372            0 :   real(dp)  :: re_zvals(nomega),im_zvals(nomega)
     373              : !  real(dp)  :: orig_refval(nomega),orig_imfval(nomega)
     374            0 :   complex(gwp) :: pole_func(nomega)
     375              : ! *********************************************************************
     376              : 
     377            0 :   npoles = ncoeff/3
     378            0 :   re_zvals(:) = REAL(omega(:))
     379            0 :   im_zvals(:) = AIMAG(omega(:))
     380              : 
     381              :   ! Normalise
     382            0 :   norm    = MAXVAL(ABS(imfval))
     383            0 :   invnorm = 1.0_gwp/norm
     384            0 :   refval  = invnorm*refval
     385            0 :   imfval  = invnorm*imfval
     386              : 
     387              :   ! Loop over poles to fit
     388            0 :   do ip=1,npoles
     389            0 :     idx = 3*(ip-1)+1
     390              :     ! Initialise pole
     391            0 :     call init_single_peak(omega,refval,imfval,nomega,nfreqre,thiscoeff,prtvol)
     392            0 :     if (present(startcoeff)) then
     393            0 :       startcoeff(idx:idx+2) = thiscoeff(1:3)
     394              :     end if
     395              :     ! Make fit
     396              : #ifdef HAVE_LEVMAR
     397              :     call dfit_re_and_im_screening(re_zvals,im_zvals,imfval,refval,&
     398              : &    nomega,3,thiscoeff,prtvol)
     399              : #else
     400            0 :     ABI_ERROR(' ABINIT was not compiled with the levmar library!')
     401              : #endif
     402              :     ! Remove current fit
     403            0 :     call re_and_im_screening(omega,pole_func,nomega,thiscoeff,3)
     404            0 :     refval(:) = refval(:) -  REAL(pole_func(:))
     405            0 :     imfval(:) = imfval(:) - AIMAG(pole_func(:))
     406            0 :     coeff(idx:idx+2) = thiscoeff(1:3)
     407            0 :     coeff(idx) = norm*coeff(idx)
     408              :   end do
     409              : 
     410            0 : end subroutine sequential_fitting
     411              : !!***
     412              : 
     413              : !!****f* m_model_screening/init_peaks_from_grid
     414              : !! NAME
     415              : !!  init_peaks_from_grid
     416              : !!
     417              : !! FUNCTION
     418              : !!
     419              : !!  Find an initial guess of coefficents from the "valleys" and "hills" in
     420              : !!   the complex plane.
     421              : !!
     422              : !! INPUTS
     423              : !!  omega      = (complex) Real and imaginary part of the frequency points
     424              : !!  yvals      = The function to be fitted in the complex plane
     425              : !!  coeff      = The coefficients in order: A_1,B_1,C_1,A_2,B_2,C_2,...,A_n,B_n,C_n
     426              : !!  nomega     = number of fit points
     427              : !!  ncoeff     = number of coefficients
     428              : !!  prtvol   = Verbosity of diagnostics
     429              : !!
     430              : !! OUTPUT
     431              : !!
     432              : !! NOTES
     433              : !!
     434              : !! SOURCE
     435              : 
     436            0 : subroutine init_peaks_from_grid(omega,fval,nomega,nfreqre,nfreqim,coeff,ncoeff,prtvol)
     437              : 
     438              : !Arguments ------------------------------------
     439              : !scalars
     440              :   integer,intent(in)   :: nomega,nfreqre,nfreqim,ncoeff,prtvol
     441              : !arrays
     442              :   complex(dp) ,intent(in)  :: omega(nomega)
     443              :   real(gwp)   ,intent(out) :: coeff(ncoeff)
     444              :   complex(gwp),intent(in)  :: fval(nomega)
     445              : 
     446              : !Local variables-------------------------------
     447              : !scalars
     448              :   integer :: npoles,iline,idx,ip
     449              :   real(gwp) :: pol,gam,maxv,df,dk,val2,b2,osc,val1
     450              :   real(gwp) :: temp1,temp2,temp3
     451              : 
     452              : !arrays
     453            0 :   integer :: ploc(ncoeff/3)
     454              : ! *********************************************************************
     455              : 
     456            0 :   npoles = ncoeff/3
     457              : 
     458              : ! Map the evolution of peaks if prtvol>10
     459            0 :   if (prtvol>10) then
     460            0 :     call print_peaks(omega,fval,nomega,nfreqre,nfreqim)
     461              :   end if ! prtvol>10
     462              : 
     463              : ! Count the number of peaks per line and find the location of the
     464              : ! constant-imaginary frequency line wich has at least a number of
     465              : ! peaks commensurate with the requested number of poles
     466            0 :   call find_peaks(fval,nomega,nfreqre,nfreqim,ploc,npoles,iline)
     467            0 :   write(std_out,*) ' Optimum peak locations:',ploc
     468            0 :   write(std_out,*) '               on iline:',iline
     469              : ! Now fit the peaks. A linear interpolation along the imaginary
     470              : !  direction is used to get a rough estimate of the width of
     471              : !  the peak.
     472            0 :   do ip=1,npoles
     473            0 :     pol  = REAL(omega(ploc(ip)))
     474            0 :     maxv = AIMAG(fval(ploc(ip)))
     475            0 :     write(std_out,*) ' maxv:',maxv
     476            0 :     if (ploc(ip)<nfreqre+1) then ! We are right on the real axis
     477            0 :       if (ploc(ip)==1) then ! Peak is at origin (Drude peak, i.e. metal)
     478            0 :         b2   = AIMAG(omega(nfreqre+1))
     479            0 :         val2 = AIMAG(fval(nfreqre+1))
     480            0 :         write(std_out,*) '1: ploc:',ploc(ip),' b2:',b2,' val2:',val2
     481              :       else ! Second value will be in c-plane
     482            0 :         idx  = nfreqre+nfreqim+ploc(ip)-1
     483            0 :         b2   = AIMAG(omega(idx))
     484            0 :         val2 = AIMAG(fval(idx))
     485            0 :         write(std_out,*) '2: ploc:',ploc(ip),' b2:',b2,' val2:',val2
     486              :       end if
     487            0 :     else if (ploc(ip)<nfreqre+nfreqim+1) then ! We are right on the imaginary axis
     488            0 :       if (ploc(ip)==nfreqre+nfreqim) then
     489            0 :         ABI_ERROR(' Peak in upper left corner. This should never happen')
     490              :       end if
     491            0 :       b2   = AIMAG(omega(ploc(ip)+1))
     492            0 :       val2 = AIMAG(fval(ploc(ip)+1))
     493            0 :         write(std_out,*) '3: ploc:',ploc(ip),' b2:',b2,' val2:',val2
     494              :     else ! We are in the complex plane
     495            0 :       idx  = ploc(ip)+nfreqre-1
     496            0 :       b2   = AIMAG(omega(idx))
     497            0 :       val2 = AIMAG(fval(idx))
     498            0 :       write(std_out,*) '4: ploc:',ploc(ip),' idx:',idx,' b2:',b2,' val2:',val2
     499              :     end if
     500            0 :     df = ABS(val2 - maxv)
     501            0 :     dk = df/b2
     502            0 :     gam = -ABS(val2/dk)
     503              :     !temp1 = SQRT(-b2*b2*val2*(val2+maxv)+(maxv*maxv)**2)
     504              :     !temp2 = b2*(two*pol*pol+b2*b2)*val2-b2*maxv*pol*pol
     505              :     !temp3 = (pol*pol+b2*b2)*val2+maxv*pol*pol
     506              :     !gam = -((temp1-temp2)/temp3)
     507            0 :     if (gam>zero) gam = ((temp1+temp2)/temp3)
     508            0 :     osc = maxv*gam*pol
     509            0 :     idx = 3*(ip-1)+1
     510            0 :     coeff(idx  ) = osc ! Oscillator strength
     511            0 :     coeff(idx+1) = pol ! Position of maximum
     512            0 :     coeff(idx+2) = gam ! Spread of function
     513            0 :     if (prtvol>9) then
     514            0 :       write(std_out,'(a,a,i0)') ch10,' Pole no,: ',ip
     515            0 :       write(std_out,'(a,ES16.8)')    '  Osc. strength:',osc
     516            0 :       write(std_out,'(a,ES16.8,a)')  '  Peak location:',pol*Ha_eV,' eV'
     517            0 :       write(std_out,'(a,ES16.8,a)')  '     Peak width:',gam*Ha_eV,' eV'
     518            0 :       val2 = gam*half
     519            0 :       val1 = SIGN(1.0_gwp,pol*pol-val2*val2)*SQRT(ABS(pol*pol-val2*val2))
     520            0 :       write(std_out,'(a,ES16.8,a)')  ' Re[z] for pole:',val1*Ha_eV,' eV'
     521            0 :       write(std_out,'(a,ES16.8,a)')  ' Im[z] for pole:',val2*Ha_eV,' eV'
     522            0 :       write(std_out,'(a,ES16.8)')    '      Amplitude:',osc*half/ABS(val1)
     523              :     end if
     524              :   end do
     525              : 
     526            0 : end subroutine init_peaks_from_grid
     527              : !!***
     528              : 
     529              : !!****f* m_model_screening/init_single_peak
     530              : !! NAME
     531              : !!  init_single_peak
     532              : !!
     533              : !! FUNCTION
     534              : !!  Initialise a single peak by using the behaviour along the imaginary axis
     535              : !!   and the main peak
     536              : !!
     537              : !! INPUTS
     538              : !!  omega      = (complex) Real and imaginary part of the frequency points
     539              : !!  yvals      = The function to be fitted in the complex plane
     540              : !!  coeff      = The coefficients in order: A_1,B_1,C_1,A_2,B_2,C_2,...,A_n,B_n,C_n
     541              : !!  nomega     = number of fit points
     542              : !!  ncoeff     = number of coefficients
     543              : !!  prtvol     = Verbosity of diagnostics
     544              : !!
     545              : !! OUTPUT
     546              : !!
     547              : !! NOTES
     548              : !!
     549              : !! SOURCE
     550              : 
     551            0 : subroutine init_single_peak(omega,refval,imfval,nomega,nfreqre,coeff,prtvol)
     552              : 
     553              : !Arguments ------------------------------------
     554              : !scalars
     555              :   integer,intent(in)   :: nomega,nfreqre,prtvol
     556              : !arrays
     557              :   complex(dp),intent(in)  :: omega(nomega)
     558              :   real(gwp)  ,intent(out) :: coeff(3)
     559              :   real(gwp)  ,intent(in) :: refval(nomega),imfval(nomega)
     560              : 
     561              : !Local variables-------------------------------
     562              : !scalars
     563              :   integer :: maxpos,idx
     564              :   real(gwp) :: pol,osc,gam,val1,val2,pol_sq
     565              : 
     566              : ! *********************************************************************
     567              : 
     568            0 :   maxpos = MAXLOC(ABS(imfval(1:nfreqre)),1)
     569            0 :   if (maxpos==1) maxpos = MAXLOC(ABS(imfval(2:nfreqre)),1)
     570            0 :   pol = REAL(omega(maxpos))
     571            0 :   pol_sq = pol*pol
     572            0 :   osc = -refval(1)*pol_sq
     573            0 :   idx = nfreqre+1
     574            0 :   val2 = refval(idx)
     575            0 :   val1 = osc+val2*pol_sq+val2*AIMAG(omega(idx))*AIMAG(omega(idx))
     576            0 :   gam  = -ABS(val1/(AIMAG(omega(idx))*val2))
     577              : 
     578            0 :   coeff(1) = osc
     579            0 :   coeff(2) = pol
     580            0 :   coeff(3) = gam
     581              : 
     582            0 :   if (prtvol>9) then
     583            0 :     write(std_out,'(a,ES16.8)')    '  Osc. strength:',osc
     584            0 :     write(std_out,'(a,ES16.8,a)')  '  Peak location:',pol*Ha_eV,' eV'
     585            0 :     write(std_out,'(a,ES16.8,a)')  '     Peak width:',gam*Ha_eV,' eV'
     586            0 :     val2 = gam*half
     587            0 :     val1 = SIGN(1.0_gwp,pol*pol-val2*val2)*SQRT(ABS(pol*pol-val2*val2))
     588            0 :     write(std_out,'(a,ES16.8,a)')  ' Re[z] for pole:',val1*Ha_eV,' eV'
     589            0 :     write(std_out,'(a,ES16.8,a)')  ' Im[z] for pole:',val2*Ha_eV,' eV'
     590            0 :     write(std_out,'(a,ES16.8)')    '      Amplitude:',osc*half/ABS(val1)
     591              :   end if
     592              : 
     593            0 : end subroutine init_single_peak
     594              : !!***
     595              : 
     596              : !!****f* m_model_screening/init_peaks_even_dist
     597              : !! NAME
     598              : !!  init_peaks_even_dist
     599              : !!
     600              : !! FUNCTION
     601              : !!
     602              : !!  Distribute the peaks evenly along a line in the complex plane and
     603              : !!   normalise.
     604              : !!
     605              : !! INPUTS
     606              : !!  omega      = (complex) Real and imaginary part of the frequency points
     607              : !!  yvals      = The function to be fitted in the complex plane
     608              : !!  coeff      = The coefficients in order: A_1,B_1,C_1,A_2,B_2,C_2,...,A_n,B_n,C_n
     609              : !!  nomega     = number of fit points
     610              : !!  ncoeff     = number of coefficients
     611              : !!  prtvol     = Verbosity of diagnostics
     612              : !!
     613              : !! OUTPUT
     614              : !!
     615              : !! NOTES
     616              : !!
     617              : !! SOURCE
     618              : 
     619            0 : subroutine init_peaks_even_dist(omega,fval,nomega,nfreqre,coeff,ncoeff,prtvol)
     620              : 
     621              : !Arguments ------------------------------------
     622              : !scalars
     623              :   integer,intent(in)   :: nomega,nfreqre,ncoeff,prtvol
     624              : !arrays
     625              :   complex(dp) ,intent(in)  :: omega(nomega)
     626              :   real(gwp)   ,intent(out) :: coeff(ncoeff)
     627              :   complex(gwp),intent(in)  :: fval(nomega)
     628              : 
     629              : !Local variables-------------------------------
     630              : !scalars
     631              :   integer :: npoles,ip,idx,iw
     632              :   real(gwp) :: delta,norm,div,val1,val2,osc,pol,gam
     633              : ! *********************************************************************
     634              : 
     635            0 :   npoles = ncoeff/3
     636            0 :   div = real(npoles,gwp)
     637              : 
     638            0 :   delta = (omega(nfreqre)-omega(1))/(div+1.0_gwp)
     639              :   ! Integrate function along real axis (trapezoid rule) and have normalised
     640              :   ! oscillator strengths
     641            0 :   norm = fval(1)*half
     642            0 :   do iw=2,nfreqre-1
     643            0 :     norm = norm + fval(iw)
     644              :   end do
     645            0 :   norm = norm + fval(nfreqre)*half
     646            0 :   norm = norm*(omega(nfreqre)-omega(1))/real(nfreqre,gwp)
     647            0 :   norm = norm/div
     648              : 
     649            0 :   do ip=1,npoles
     650            0 :     idx = 3*(ip-1)+1
     651            0 :     pol = delta*ip   ! Position of maximum
     652            0 :     gam = 0.1_gwp ! Spread of function
     653            0 :     val2 = gam*half
     654            0 :     val1 = SQRT(pol*pol-val2*val2)
     655            0 :     osc = norm*val1*two
     656            0 :     coeff(idx  ) = osc!*(-1.0_gwp)**(ip-1)
     657            0 :     coeff(idx+1) = pol   ! Position of maximum
     658            0 :     coeff(idx+2) = -gam ! Spread of function
     659            0 :     if (prtvol>9) then
     660            0 :       write(std_out,'(a,a,i0)') ch10,' Pole no,: ',ip
     661            0 :       write(std_out,'(a,ES16.8)')    '  Osc. strength:',osc
     662            0 :       write(std_out,'(a,ES16.8,a)')  '  Peak location:',pol*Ha_eV,' eV'
     663            0 :       write(std_out,'(a,ES16.8,a)')  '     Peak width:',gam*Ha_eV,' eV'
     664            0 :       val2 = gam*half
     665            0 :       val1 = SIGN(1.0_gwp,pol*pol-val2*val2)*SQRT(ABS(pol*pol-val2*val2))
     666            0 :       write(std_out,'(a,ES16.8,a)')  ' Re[z] for pole:',val1*Ha_eV,' eV'
     667            0 :       write(std_out,'(a,ES16.8,a)')  ' Im[z] for pole:',val2*Ha_eV,' eV'
     668            0 :       write(std_out,'(a,ES16.8)')    '      Amplitude:',osc*half/ABS(val1)
     669              :     end if
     670              :   end do
     671              : 
     672            0 : end subroutine init_peaks_even_dist
     673              : !!***
     674              : 
     675              : !!****f* m_model_screening/print_peaks
     676              : !! NAME
     677              : !!  print_peaks
     678              : !!
     679              : !! FUNCTION
     680              : !!
     681              : !!  Find and output the location of peaks on the grid in a file
     682              : !!
     683              : !! INPUTS
     684              : !!  omega      = (complex) Real and imaginary part of the frequency points
     685              : !!  fvals      = The function to be fitted in the complex plane
     686              : !!  nomega     = number of fit points
     687              : !!  nfreqre    = number or imaginary gridlines
     688              : !!  nfreqim    = number of real gridlines
     689              : !!
     690              : !! OUTPUT
     691              : !!
     692              : !! NOTES
     693              : !!
     694              : !! SOURCE
     695              : 
     696            0 : subroutine print_peaks(omega,fval,nomega,nfreqre,nfreqim)
     697              : 
     698              : !Arguments ------------------------------------
     699              : !scalars
     700              :   integer,intent(in)   :: nomega,nfreqre,nfreqim
     701              : !arrays
     702              :   complex(dp) ,intent(in)  :: omega(nomega)
     703              :   complex(gwp),intent(in)  :: fval(nomega)
     704              : 
     705              : !Local variables-------------------------------
     706              : !scalars
     707              :   integer :: ire,iim,unt_tmp
     708              :   integer :: idx1,idx2,idx3
     709              :   real(gwp) :: rez,imz,val1,val2,val3
     710              :   character(len=500) :: msg
     711              : ! *********************************************************************
     712              : 
     713            0 :   if (open_file("grid_peak_tree.dat", msg, newunit=unt_tmp) /= 0) then
     714            0 :     ABI_ERROR(msg)
     715              :   end if
     716              : 
     717            0 :   do iim=nfreqim,1,-1
     718              : !    write(std_out,*) ' iim:',iim
     719              : !   Check first points
     720            0 :     idx1 = nfreqre+iim
     721            0 :     idx2 = nfreqre+nfreqim+1+(nfreqre-1)*(iim-1)
     722              : !    write(std_out,*) ' idx1:',idx1,' idx2:',idx2
     723            0 :     val1 = AIMAG(fval(idx1))
     724            0 :     val2 = AIMAG(fval(idx2))
     725            0 :     if (ABS(val1)>ABS(val2)) then
     726            0 :       rez = REAL(omega(idx1))
     727            0 :       imz = AIMAG(omega(idx1))
     728            0 :       write(unt_tmp,'(2f8.2,4x,ES16.8)') rez*Ha_eV,imz*Ha_eV,val1
     729              :     end if
     730              : !   Do all but the last
     731            0 :     do ire=1,nfreqre-4
     732            0 :        idx1 = nfreqre+nfreqim+1+(nfreqre-1)*(iim-1)+ire
     733            0 :        idx2 = idx1+1
     734            0 :        idx3 = idx1+2
     735              : !       write(std_out,*) ' idx1:',idx1,' idx2:',idx2,' idx3:',idx3
     736            0 :        rez = REAL(omega(idx2))
     737            0 :        imz = AIMAG(omega(idx2))
     738            0 :        val1 = AIMAG(fval(idx1))
     739            0 :        val2 = AIMAG(fval(idx2))
     740            0 :        val3 = AIMAG(fval(idx3))
     741            0 :        if (((val1<val2).AND.(val2>val3))) then
     742            0 :          if (sign(1.0_gwp,val2)<zero) CYCLE
     743            0 :          write(unt_tmp,'(2f8.2,4x,ES16.8)') rez*Ha_eV,imz*Ha_eV,val2
     744            0 :        else if (((val1>val2).AND.(val2<val3))) then
     745            0 :          if (sign(1.0_gwp,val2)>zero) CYCLE
     746            0 :          write(unt_tmp,'(2f8.2,4x,ES16.8)') rez*Ha_eV,imz*Ha_eV,val2
     747              :        end if
     748              :     end do
     749              : !   Check last point
     750            0 :     idx1 = nfreqre+nfreqim+1+(nfreqre-1)*(iim-1)+nfreqre-3
     751            0 :     idx2 = idx1 + 1
     752              : !   write(std_out,*) ' idx1:',idx1,' idx2:',idx2
     753            0 :     rez = REAL(omega(idx2))
     754            0 :     imz = AIMAG(omega(idx2))
     755            0 :     val1 = AIMAG(fval(idx1))
     756            0 :     val2 = AIMAG(fval(idx2))
     757            0 :     if (ABS(val1)<ABS(val2)) then
     758            0 :       write(unt_tmp,'(2f8.2,4x,ES16.8)') rez*Ha_eV,imz*Ha_eV,val2
     759              :     end if
     760              :   end do
     761              : ! finally, do the purely real axis
     762              : ! Check first points
     763            0 :   idx1 = 1; idx2 = 2
     764            0 :   val1 = AIMAG(fval(idx1)); val2 = AIMAG(fval(idx2))
     765            0 :   if (ABS(val1)>ABS(val2)) then
     766            0 :     rez = REAL(omega(idx1))
     767            0 :     imz = AIMAG(omega(idx1))
     768            0 :     write(unt_tmp,'(2f8.2,4x,ES16.8)') rez*Ha_eV,imz*Ha_eV,val1
     769              :   end if
     770            0 :   do ire=2,nfreqre-3
     771            0 :     idx1 = ire; idx2 = idx1+1; idx3 = idx1+2
     772            0 :     rez = REAL(omega(idx2))
     773            0 :     imz = AIMAG(omega(idx2))
     774            0 :     val1 = AIMAG(fval(idx1))
     775            0 :     val2 = AIMAG(fval(idx2))
     776            0 :     val3 = AIMAG(fval(idx3))
     777            0 :     if (((val1<val2).AND.(val2>val3))) then
     778            0 :       if (sign(1.0_gwp,val2)<zero) CYCLE
     779            0 :       write(unt_tmp,'(2f8.2,4x,ES16.8)') rez*Ha_eV,imz*Ha_eV,val2
     780            0 :     else if (((val1>val2).AND.(val2<val3))) then
     781            0 :       if (sign(1.0_gwp,val2)>zero) CYCLE
     782            0 :       write(unt_tmp,'(2f8.2,4x,ES16.8)') rez*Ha_eV,imz*Ha_eV,val2
     783              :     end if
     784              :   end do
     785              : ! Check last point
     786            0 :   idx1 = nfreqre-2
     787            0 :   idx2 = idx1 + 1
     788              : !  write(std_out,*) ' idx1:',idx1,' idx2:',idx2
     789            0 :   rez = REAL(omega(idx2))
     790            0 :   imz = AIMAG(omega(idx2))
     791            0 :   val1 = AIMAG(fval(idx1))
     792            0 :   val2 = AIMAG(fval(idx2))
     793            0 :   if (ABS(val1)<ABS(val2)) then
     794            0 :     write(unt_tmp,'(2f8.2,4x,ES16.8)') rez*Ha_eV,imz*Ha_eV,val2
     795              :   end if
     796              : 
     797            0 :   close(unt_tmp)
     798              : 
     799            0 : end subroutine print_peaks
     800              : !!***
     801              : 
     802              : !!****f* m_model_screening/find_peaks
     803              : !! NAME
     804              : !!  find_peaks
     805              : !!
     806              : !! FUNCTION
     807              : !!
     808              : !!  Find the location of the highest peaks along gridlines starting at the real axis
     809              : !!  and then moving towards higher imaginary frequencies. Stop when enough
     810              : !!  peaks to satisfy the number of poles needed has been found
     811              : !!
     812              : !! INPUTS
     813              : !!  omega      = (complex) Real and imaginary part of the frequency points
     814              : !!  fvals      = The function to be fitted in the complex plane
     815              : !!  nomega     = number of fit points
     816              : !!  nfreqre    = number or imaginary gridlines
     817              : !!  nfreqim    = number of real gridlines
     818              : !!
     819              : !! OUTPUT
     820              : !!
     821              : !! NOTES
     822              : !!
     823              : !! SOURCE
     824              : 
     825            0 : subroutine find_peaks(fval,nomega,nfreqre,nfreqim,ploc,npoles,iline)
     826              : 
     827              : !Arguments ------------------------------------
     828              : !scalars
     829              :   integer,intent(in)     :: nomega,nfreqre,nfreqim,npoles
     830              :   integer, intent(inout) :: iline
     831              : !arrays
     832              :   integer    ,intent(inout) :: ploc(npoles)
     833              :   complex(gwp), intent(in) :: fval(nomega)
     834              : 
     835              : !Local variables-------------------------------
     836              : !scalars
     837              :   integer    :: ire,iim,ipoles
     838              :   integer    :: idx1,idx2,idx3,ipol
     839              :   real(gwp) :: val1,val2,val3
     840              : !arrays
     841            0 :   integer :: ploc_prev(npoles)
     842            0 :   real    :: pval(npoles),pval_prev(npoles)
     843              : ! *********************************************************************
     844              : 
     845            0 :   ploc=-1; ploc_prev=-1
     846            0 :   pval=zero; pval_prev=zero; ipol=1; ipoles=0
     847              : 
     848              : ! First do a line along the real axis
     849            0 :   idx1 = 1; idx2 = 2
     850            0 :   val1 = AIMAG(fval(idx1)); val2 = AIMAG(fval(idx2))
     851            0 :   if (ABS(val1)>ABS(val2)) then
     852            0 :     ipoles = ipoles + 1
     853            0 :     ploc(1)=idx1; pval(1)=val1
     854            0 :     write(std_out,*) ' pval:',pval
     855            0 :     write(std_out,*) ' ploc:',ploc
     856              :   end if
     857            0 :   do ire=2,nfreqre-3
     858            0 :     idx1 = ire; idx2 = idx1+1; idx3 = idx1+2
     859            0 :     val1 = AIMAG(fval(idx1))
     860            0 :     val2 = AIMAG(fval(idx2))
     861            0 :     val3 = AIMAG(fval(idx3))
     862            0 :     if (((val1<val2).AND.(val2>val3))) then
     863            0 :       if (sign(1.0_gwp,val2)<zero) CYCLE
     864            0 :       ipoles = ipoles + 1
     865            0 :       if (ANY( ABS(pval(:))<ABS(val2) )) then
     866            0 :         ipol = MINLOC(ABS(pval(:)),1)
     867            0 :         ploc(ipol)=idx2; pval(ipol)=val2
     868            0 :         write(std_out,*) ' pval:',pval
     869            0 :         write(std_out,*) ' ploc:',ploc
     870              :       end if
     871            0 :     else if (((val1>val2).AND.(val2<val3))) then
     872            0 :       if (sign(1.0_gwp,val2)>zero) CYCLE
     873            0 :       ipoles = ipoles + 1
     874            0 :       if (ANY( ABS(pval(:))<ABS(val2) )) then
     875            0 :         ipol = MINLOC(ABS(pval(:)),1)
     876            0 :         ploc(ipol)=idx2; pval(ipol)=val2
     877            0 :         write(std_out,*) ' pval:',pval
     878            0 :         write(std_out,*) ' ploc:',ploc
     879              :       end if
     880              :     end if
     881              :   end do
     882              : ! Check last point
     883            0 :   idx1 = nfreqre-2
     884            0 :   idx2 = idx1 + 1
     885              : !  write(std_out,*) ' idx1:',idx1,' idx2:',idx2
     886            0 :   val1 = AIMAG(fval(idx1))
     887            0 :   val2 = AIMAG(fval(idx2))
     888            0 :   if (ABS(val1)<ABS(val2)) then
     889            0 :     ipoles = ipoles + 1
     890            0 :     if (ANY( ABS(pval(:))<ABS(val2) )) then
     891            0 :       ipol = MINLOC(ABS(pval(:)),1)
     892            0 :       ploc(ipol)=idx2; pval(ipol)=val2
     893            0 :        write(std_out,*) ' pval:',pval
     894            0 :        write(std_out,*) ' ploc:',ploc
     895              :     end if
     896              :   end if
     897            0 :   write(std_out,'(a,i0)') ' Number of poles real axis:',ipoles
     898              : 
     899              : 
     900            0 :   ploc_prev = ploc; pval_prev = pval
     901              : 
     902              : ! Do the rest of the imaginary grid until total
     903              : !  number of peaks found equals npoles or less
     904            0 :   do iim=1,nfreqim-1
     905            0 :     ploc=-1; pval=zero; ipol=1; ipoles=0
     906            0 :     idx1 = nfreqre+iim
     907            0 :     idx2 = nfreqre+nfreqim+1+(nfreqre-1)*(iim-1)
     908              : !    write(std_out,*) ' idx1:',idx1,' idx2:',idx2
     909            0 :     val1 = AIMAG(fval(idx1))
     910            0 :     val2 = AIMAG(fval(idx2))
     911            0 :     if (ABS(val1)>ABS(val2)) then
     912            0 :       ipoles = ipoles + 1
     913            0 :       ploc(1)=idx1; pval(1)=val1
     914            0 :       write(std_out,*) ' pval:',pval
     915            0 :       write(std_out,*) ' ploc:',ploc
     916              :     end if
     917              : !   Do all but the last
     918            0 :     do ire=1,nfreqre-4
     919            0 :        idx1 = nfreqre+nfreqim+1+(nfreqre-1)*(iim-1)+ire
     920            0 :        idx2 = idx1+1
     921            0 :        idx3 = idx1+2
     922              : !       write(std_out,*) ' idx1:',idx1,' idx2:',idx2,' idx3:',idx3
     923            0 :        val1 = AIMAG(fval(idx1))
     924            0 :        val2 = AIMAG(fval(idx2))
     925            0 :        val3 = AIMAG(fval(idx3))
     926            0 :        if (((val1<val2).AND.(val2>val3))) then
     927            0 :          if (sign(1.0_gwp,val2)<zero) CYCLE
     928            0 :          ipoles = ipoles + 1
     929            0 :          if (ANY( ABS(pval(:))<ABS(val2) )) then
     930            0 :            ipol = MINLOC(ABS(pval(:)),1)
     931            0 :            ploc(ipol)=idx2; pval(ipol)=val2
     932            0 :            write(std_out,*) ' pval:',pval
     933            0 :            write(std_out,*) ' ploc:',ploc
     934              :          end if
     935            0 :        else if (((val1>val2).AND.(val2<val3))) then
     936            0 :          if (sign(1.0_gwp,val2)>zero) CYCLE
     937            0 :          ipoles = ipoles + 1
     938            0 :          if (ANY( ABS(pval(:))<ABS(val2) )) then
     939            0 :            ipol = MINLOC(ABS(pval(:)),1)
     940            0 :            ploc(ipol)=idx2; pval(ipol)=val2
     941            0 :            write(std_out,*) ' pval:',pval
     942            0 :            write(std_out,*) ' ploc:',ploc
     943              :          end if
     944              :        end if
     945              :     end do
     946              : !   Check last point
     947            0 :     idx1 = nfreqre+nfreqim+1+(nfreqre-1)*(iim-1)+nfreqre-3
     948            0 :     idx2 = idx1 + 1
     949              : !   write(std_out,*) ' idx1:',idx1,' idx2:',idx2
     950            0 :     val1 = AIMAG(fval(idx1))
     951            0 :     val2 = AIMAG(fval(idx2))
     952            0 :     if (ABS(val1)<ABS(val2)) then
     953            0 :       ipoles = ipoles + 1
     954            0 :       if (ANY( ABS(pval(:))<ABS(val2) )) then
     955            0 :         ipol = MINLOC(ABS(pval(:)),1)
     956            0 :         ploc(ipol)=idx2; pval(ipol)=val2
     957            0 :          write(std_out,*) ' pval:',pval
     958            0 :          write(std_out,*) ' ploc:',ploc
     959              :       end if
     960              :     end if
     961            0 :     write(std_out,'(2(a,i0))') ' Line,:',iim,' ipoles:',ipoles
     962            0 :     if (ipoles<=npoles) then
     963            0 :       iline = iim - 1
     964            0 :       ploc = ploc_prev
     965              :       EXIT
     966              :     end if
     967              : 
     968            0 :     ploc_prev = ploc; pval_prev = pval
     969              : 
     970              :  end do
     971              : 
     972            0 : end subroutine find_peaks
     973              : !!***
     974              : 
     975              : !!****f* m_model_screening/remove_phase
     976              : !! NAME
     977              : !!  remove_phase
     978              : !!
     979              : !! FUNCTION
     980              : !!  Find out what the complex phase factor is for off-diagonal elements
     981              : !!   and unmix the components.
     982              : !!
     983              : !! INPUTS
     984              : !!  fvals  = The function to be fitted in the complex plane.
     985              : !!  nomega = Number of fit points.
     986              : !!  nfreqre    = number or imaginary gridlines
     987              : !!  phase  = The phase angle.
     988              : !!
     989              : !! OUTPUT
     990              : !!
     991              : !! NOTES
     992              : !!
     993              : !! SOURCE
     994              : 
     995            0 : subroutine remove_phase(fval,nomega,phase)
     996              : 
     997              : !Arguments ------------------------------------
     998              : !scalars
     999              :   integer,    intent(in)  :: nomega
    1000              :   real(gwp), intent(out) :: phase
    1001              : !arrays
    1002              :   complex(gwp), intent(inout) :: fval(nomega)
    1003              : 
    1004              : !Local variables-------------------------------
    1005              : !scalars
    1006              :   integer       :: io
    1007              :   real(gwp)    :: a,b,retemp,imtemp
    1008              : ! *********************************************************************
    1009              : 
    1010              : ! The phase can be found by checking when the function is
    1011              : !  identically zero along the imaginary axis
    1012            0 :   if (ABS(AIMAG(fval(1)))<tol14) then ! Phase is zero
    1013            0 :     phase = zero
    1014            0 :     RETURN
    1015            0 :   else if (ABS(REAL(fval(1)))<tol14) then ! Phase is exactly pi/2
    1016            0 :     phase = pi*half
    1017            0 :     a = zero
    1018            0 :     b = -1.0_gwp
    1019              :   else
    1020            0 :     phase = ATAN(AIMAG(fval(1))/REAL(fval(1)))
    1021            0 :     a = COS(phase)
    1022            0 :     b = -SIN(phase)
    1023              :   end if
    1024              : ! Rotate values
    1025            0 :   do io=1,nomega
    1026            0 :     retemp = REAL(fval(io))
    1027            0 :     imtemp = AIMAG(fval(io))
    1028            0 :     fval(io) = CMPLX(a*retemp-b*imtemp,a*imtemp+b*retemp)
    1029              :   end do
    1030              : 
    1031              : end subroutine remove_phase
    1032              : !!***
    1033              : 
    1034              : END MODULE m_model_screening
    1035              : !!***
        

Generated by: LCOV version 2.3-1