LCOV - code coverage report
Current view: top level - src/98_main - lruj.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 78.8 % 283 223
Test Date: 2026-11-11 18:45:25 Functions: 100.0 % 4 4
Branches: 52.0 % 548 285

             Branch data     Line data    Source code
       1                 :             : !!****p* ABINIT/lruj
       2                 :             : !! NAME
       3                 :             : !! lruj
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !!  Linear Response U and J:
       7                 :             : !!  Determines Hubbard U or Hund's J from series of *DS*_LRUJ.nc
       8                 :             : !!  files containing information regarding the perturbation applied to a particular
       9                 :             : !!  atom and the resulting occupations/magnetizations. The procedure implemented
      10                 :             : !!  is that of the SCF linear response for the Hubbard U (Phys. Rev. B 71,035105)
      11                 :             : !!  and the Hund's J (Phys. Rev. B 98, 235157) parameters.
      12                 :             : !!  This protocol was coded up in November 2022 by Lorien MacEnulty (macenulty.com),
      13                 :             : !!  doctoral researcher in the Quantum Theory of Materials group (theoryofmaterials.com)
      14                 :             : !!  at Trinity College Dublin, headed by Dr. David O'Regan.
      15                 :             : !!
      16                 :             : !! COPYRIGHT
      17                 :             : !!  Copyright (C) 1998-2026 ABINIT group (LMac)
      18                 :             : !!  This file is distributed under the terms of the
      19                 :             : !!  GNU General Public License, see ~abinit/COPYING
      20                 :             : !!  or http://www.gnu.org/copyleft/gpl.txt .
      21                 :             : !!  For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
      22                 :             : !!
      23                 :             : !! INPUTS
      24                 :             : !!  Executed as ./lruj *LRUJ.nc FILE1 FILE2 FILE3 ... [--d 5] [--help] [--version]
      25                 :             : !!  --d <n> = Command line argument: highest degree of intended polynomial fits
      26                 :             : !!  *DS*_LRUJ.nc files = gives data from perturbative Abinit calculations
      27                 :             : !!
      28                 :             : !! OUTPUT
      29                 :             : !!  std_out = log file
      30                 :             : !!
      31                 :             : !! SOURCE
      32                 :             : 
      33                 :             : #if defined HAVE_CONFIG_H
      34                 :             : #include "config.h"
      35                 :             : #endif
      36                 :             : 
      37                 :             : #include "abi_common.h"
      38                 :             : 
      39                 :             : 
      40                 :           4 : program lruj
      41                 :             : 
      42                 :           4 :  use defs_basis
      43                 :             :  use m_xmpi
      44                 :             :  use m_abicore
      45                 :             :  use m_build_info
      46                 :             :  use m_errors
      47                 :             :  use m_argparse
      48                 :             :  use m_crystal
      49                 :             :  use netcdf
      50                 :             :  use m_nctk
      51                 :             :  use m_yaml
      52                 :             : 
      53                 :             :  use m_fstrings,      only : itoa, sjoin, ltoa
      54                 :             :  use m_specialmsg,    only : specialmsg_getcount, herald
      55                 :             :  use m_numeric_tools, only : polynomial_regression
      56                 :             :  use m_sort,          only : sort_dp
      57                 :             :  use m_common,        only : crystal_from_file
      58                 :             :  use m_mpinfo,        only : destroy_mpi_enreg, initmpi_seq
      59                 :             :  use m_paw_uj,        only : pawuj_ini,pawuj_free,pawuj_det, macro_uj_type
      60                 :             : 
      61                 :             :  implicit none
      62                 :             : 
      63                 :             : !Local variables-------------------------------
      64                 :             : 
      65                 :             : !scalars
      66                 :             :  integer,parameter                  :: master=0
      67                 :             :  integer                            :: nproc,my_rank,comm
      68                 :             :  logical                            :: iam_master
      69                 :             : 
      70                 :             :  integer                            :: ncid,nnat,natom,prtvol,nargs,nfiles,ndtpawuj,degarg
      71                 :             :  integer                            :: ndata,nspden,macro_uj,pawujat,dmatpuopt
      72                 :             :  integer                            :: degree,mdegree,ii,ipert
      73                 :             :  real(dp)                           :: diem,ph0phiint,signum !diemix, diemixmag,
      74                 :             :  type(yamldoc_t)                    :: ydoc
      75                 :             :  !type(crystal_t)                    :: cryst
      76                 :             : 
      77                 :             : !arrays
      78                 :           4 :  integer, allocatable               :: iperm(:),pawujat_file(:),macrouj_file(:),dmatpuopt_file(:)
      79                 :           4 :  real(dp), allocatable              :: diem_file(:),ph0phiint_file(:),nspden_file(:)
      80                 :             : 
      81                 :           4 :  real(dp), allocatable              :: perts(:),occs0(:),occs(:)
      82                 :           4 :  real(dp), allocatable              :: uj_perts(:),luocc(:,:),luocc_nnat(:,:)
      83                 :           4 :  real(dp), allocatable              :: chi0coeffs(:),chicoeffs(:),chi0(:),chi(:),hubpar(:)
      84                 :           4 :  real(dp), allocatable              :: chi0err(:),chierr(:),hubparerr(:)
      85                 :             : 
      86                 :             : !characters
      87                 :             :  character(len=1)                   :: parname
      88                 :             :  character(len=5)                   :: degreename
      89                 :             :  character(len=12)                  :: regname
      90                 :             :  character(len=14)                  :: occmag
      91                 :             :  character(len=24)                  :: codename
      92                 :             :  character(len=30)                  :: diem_token
      93                 :             :  character(len=500)                 :: message,arg,msg,pertname
      94                 :           4 :  character(len=fnlen),allocatable   :: file_paths(:)
      95                 :             : 
      96                 :             : 
      97                 :             : !##########################################################################################################
      98                 :             : !##################################  Set up MPI architecture (unused)  ####################################
      99                 :             : 
     100                 :             :  !Change communicator for I/O (mandatory!)
     101                 :           4 :  call abi_io_redirect(new_io_comm=xmpi_world)
     102                 :             : 
     103                 :             :  !Initialize MPI (not used but necessary)
     104                 :           4 :  call xmpi_init()
     105                 :           4 :  comm = xmpi_world
     106                 :           4 :  nproc = xmpi_comm_size(comm)
     107                 :           4 :  my_rank = xmpi_comm_rank(comm)
     108                 :           4 :  iam_master = (my_rank == master)
     109                 :             : 
     110                 :             :  !Initialize memory profiling if it is activated
     111                 :             :  !if a full abimem.mocc report is desired, set the argument of abimem_init to "2" instead of "0"
     112                 :             :  !note that abimem.mocc files can easily be multiple GB in size so don't use this option normally
     113                 :             : #ifdef HAVE_MEM_PROFILING
     114                 :             :  call abimem_init(0)
     115                 :             : #endif
     116                 :             : 
     117                 :             :  !No MPI functionality needed for main procedure.
     118         [ -  + ]:           4 :  if (my_rank /= master) goto 100
     119                 :             : 
     120                 :             : !##########################################################################################################
     121                 :             : !######################################  Read command line options  #######################################
     122                 :             : 
     123                 :             :  !Count arguments and number of files (= #perturbations)
     124                 :           4 :  nargs = command_argument_count()
     125   [ +  -  -  +  :           4 :  ABI_MALLOC(file_paths, (nargs))
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     126                 :           4 :  nfiles = 0
     127         [ +  + ]:          22 :  do ii=1,nargs
     128                 :          18 :    call get_command_argument(ii, arg)
     129         [ -  + ]:          18 :    if (arg(1:1) == "-") exit
     130                 :          18 :    nfiles = nfiles + 1
     131   [ +  -  +  - ]:          22 :    file_paths(nfiles) = trim(arg)
     132                 :             :  end do
     133                 :             : 
     134                 :             :  !Assess options
     135         [ +  + ]:          22 :  do ii=1,command_argument_count()
     136                 :          18 :    call get_command_argument(ii, arg)
     137         [ -  + ]:          22 :    if (arg == "--version") then
     138                 :           0 :      write(std_out,"(a)") trim(abinit_version); goto 100
     139         [ -  + ]:          18 :    else if (arg == "-h" .or. arg == "--help") then
     140                 :             :      !Document the options.
     141                 :           0 :      call lruj_show_help()
     142                 :           0 :      goto 100
     143                 :             :    end if
     144                 :             :  end do
     145                 :             : 
     146                 :             :  !If no files found, exit program.
     147         [ -  + ]:           4 :  if (nfiles == 0) then
     148                 :           0 :    write(std_out, *) "Empty file list!"
     149                 :           0 :    goto 100
     150                 :             :  end if
     151                 :             : 
     152                 :             :  !Get other options from the CLI. e.g. --prtvol 0 -d 3.0
     153                 :             :  !Should be documented in lruj_show_help
     154         [ -  + ]:           4 :  ABI_CHECK(get_arg("prtvol", prtvol, msg, default=0) == 0, msg)
     155         [ -  + ]:           4 :  ABI_CHECK(get_arg("d", degarg, msg, default=1) == 0, msg)
     156                 :             : 
     157                 :             :  !Print header
     158                 :           4 :  codename='LRUJ'//repeat(' ',18)
     159                 :           4 :  call herald(codename, abinit_version, std_out)
     160                 :             : 
     161                 :             : !##########################################################################################################
     162                 :             : !######################################  Read *DSi*_LRUJ.nc files  ########################################
     163                 :             : 
     164   [ +  -  -  +  :           4 :  ABI_MALLOC(uj_perts,(nfiles))
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     165   [ +  -  -  +  :           4 :  ABI_MALLOC(macrouj_file, (nfiles))
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     166                 :             : 
     167                 :             :  !Read perturbation strengths, parameter type, #spins and #atoms
     168                 :             :  !from each file.
     169         [ +  + ]:          22 :  do ii=1,nfiles
     170         [ -  + ]:          18 :    NCF_CHECK(nctk_open_read(ncid, file_paths(ii), xmpi_comm_self))
     171         [ -  + ]:          18 :    NCF_CHECK(nf90_get_var(ncid, vid("uj_pert"), uj_perts(ii)))
     172         [ -  + ]:          18 :    NCF_CHECK(nf90_get_var(ncid, vid("macro_uj"), macrouj_file(ii)))
     173                 :          18 :    macro_uj=macrouj_file(1)
     174                 :             :    !Make sure ndtpawuj is always 4.
     175         [ -  + ]:          18 :    NCF_CHECK(nctk_get_dim(ncid, "ndtpawuj", ndtpawuj))
     176         [ -  + ]:          18 :    ABI_CHECK_IEQ(ndtpawuj, 4, "Wrong ndtpawuj")
     177         [ -  + ]:          18 :    NCF_CHECK(nctk_get_dim(ncid, "nspden", nspden))
     178         [ -  + ]:          18 :    NCF_CHECK(nctk_get_dim(ncid, "nnat", nnat))
     179         [ -  + ]:          18 :    NCF_CHECK(nctk_get_dim(ncid, "natom", natom))
     180         [ -  + ]:          22 :    NCF_CHECK(nf90_close(ncid))
     181                 :             :  end do
     182                 :             : 
     183                 :             :  !Sort files by perturbation magnitude.
     184   [ +  -  -  +  :           4 :  ABI_MALLOC(iperm, (nfiles))
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     185   [ -  +  +  +  :          58 :  iperm = [(ii, ii=1,nfiles)]
          -  +  +  +  +  
          -  +  -  -  -  
                   +  + ]
     186                 :           4 :  call sort_dp(nfiles, uj_perts, iperm, tol12)
     187   [ -  +  +  +  :          40 :  file_paths(1:nfiles) = file_paths(iperm(:))
                   +  + ]
     188         [ -  + ]:           4 :  ABI_FREE(iperm)
     189                 :             : 
     190                 :             :  !Allocate main data-holding arrays.
     191   [ +  -  -  +  :           4 :  ABI_MALLOC(luocc, (ndtpawuj, nfiles))
          +  -  -  +  -  
          +  -  +  -  +  
             -  +  -  + ]
     192   [ +  -  -  +  :           4 :  ABI_MALLOC(luocc_nnat, (ndtpawuj, nnat))
          +  -  -  +  -  
          +  -  +  -  +  
             -  +  -  + ]
     193   [ +  -  -  +  :           4 :  ABI_MALLOC(pawujat_file, (nfiles))
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     194   [ +  -  -  +  :           4 :  ABI_MALLOC(diem_file, (nfiles))
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     195   [ +  -  -  +  :           4 :  ABI_MALLOC(dmatpuopt_file, (nfiles))
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     196   [ +  -  -  +  :           4 :  ABI_MALLOC(ph0phiint_file, (nfiles))
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     197   [ +  -  -  +  :           4 :  ABI_MALLOC(nspden_file, (nfiles))
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     198                 :             : 
     199                 :             :  !Set macro_uj-specific variables, strings and constants.
     200         [ +  + ]:           4 :  if (macro_uj==4) then         !Calculation of the Hunds J parameter
     201                 :           2 :    diem_token="diemixmag"     !Unscreened response in Hund's J impacted by diemixmag
     202                 :           2 :    pertname='beta '           !Hund's J perturbation: +beta to spin up, -beta to down
     203                 :           2 :    parname='J'
     204                 :           2 :    occmag='Magnetizations'    !Magnetic moments are monitored.
     205                 :           2 :    signum=-1.0d0              !Hund's J is -1*(1/chi0-1/chi)
     206                 :             :  else
     207                 :           2 :    diem_token="diemix"        !Unscreened response in Hubbard U impacted by diemix
     208                 :           2 :    pertname='alpha'           !Hubbard U perturbation; applied equally to spins up and down
     209                 :           2 :    parname='U'
     210                 :           2 :    occmag='  Occupations'     !Total occupation is monitored.
     211                 :           2 :    signum=1.0d0               !Hubbard U is 1*(1/chi0-1/chi)
     212                 :             :  end if
     213                 :             : 
     214                 :             :  !Allocate perturbation and occupation arrays. Set the first
     215                 :             :  !to the unperturbed case (i.e., when perturbation=0.0d0).
     216   [ +  -  -  +  :           4 :  ABI_MALLOC(perts,(0:nfiles))
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     217   [ +  -  -  +  :           4 :  ABI_MALLOC(occs0,(0:nfiles))
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     218   [ +  -  -  +  :           4 :  ABI_MALLOC(occs,(0:nfiles))
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     219                 :           4 :  perts(0)=0.0d0               !Unperturbed case.
     220                 :             : 
     221                 :           4 :  write(std_out,'(a,i2)') ' Number of perturbations detected: ',nfiles
     222                 :             : 
     223                 :             :  !Open _LRUJ.nc files and read in the relevant data.
     224         [ +  + ]:          22 :  do ii=1,nfiles
     225         [ -  + ]:          18 :    NCF_CHECK(nctk_open_read(ncid, file_paths(ii), xmpi_comm_self))
     226         [ -  + ]:          18 :    NCF_CHECK(nf90_get_var(ncid, vid("pawujat"), pawujat_file(ii)))
     227                 :          18 :    pawujat=pawujat_file(1)
     228         [ -  + ]:          18 :    NCF_CHECK(nf90_get_var(ncid, vid("nspden"), nspden_file(ii)))
     229                 :          18 :    nspden=nspden_file(1)
     230         [ -  + ]:          18 :    NCF_CHECK(nf90_get_var(ncid, vid("luocc"), luocc_nnat))
     231         [ +  + ]:          90 :    luocc(:,ii) = luocc_nnat(:,pawujat)
     232         [ -  + ]:          18 :    NCF_CHECK(nf90_get_var(ncid, vid(diem_token), diem_file(ii)))
     233                 :          18 :    diem=diem_file(1)
     234         [ -  + ]:          18 :    NCF_CHECK(nf90_get_var(ncid, vid("dmatpuopt"), dmatpuopt_file(ii)))
     235                 :          18 :    dmatpuopt=dmatpuopt_file(1)
     236         [ -  + ]:          18 :    NCF_CHECK(nf90_get_var(ncid, vid("ph0phiint"), ph0phiint_file(ii)))
     237                 :          18 :    ph0phiint=ph0phiint_file(1)
     238         [ -  + ]:          18 :    NCF_CHECK(nf90_close(ncid))
     239                 :             :    !Testing if the unperturbed occupancies are equal across each run. If they
     240                 :             :    !aren't, then exit. If they are equal, then save them in appropriate arrays.
     241         [ -  + ]:          22 :    if ((ii>1).and.((occs0(0)/=luocc(1,ii)).or.(occs(0)/=luocc(2,ii)))) then
     242                 :           0 :      write(std_out,'(a)') "ERROR: Unperturbed ground state occupations across LRUJ datasets are not equal."
     243                 :           0 :      write(std_out,'(a)') "Check the consistency of input variables in your perturbative calculations:"
     244                 :           0 :      write(std_out,'(a)') "    1. Are they each reading in the same WFK file?"
     245                 :           0 :      write(std_out,'(a)') "    2. Are macro-uj, pawujat, dmatpuopt, diemix(mag) consistent"
     246                 :           0 :      write(std_out,'(a)') "       across all perturbations?"
     247                 :           0 :      write(std_out,'(a)') "If not, relaunch perturbative Abinit calculations, then"
     248                 :           0 :      write(std_out,'(2a)') "reexecute lruj utility. Exiting.",ch10
     249                 :           0 :      goto 100
     250                 :             :    else
     251                 :          18 :      perts(ii)=uj_perts(ii)*Ha_eV
     252                 :          18 :      occs0(0)=luocc(1,ii)
     253                 :          18 :      occs(0)=luocc(2,ii)
     254                 :          18 :      occs0(ii)=luocc(3,ii)
     255                 :          18 :      occs(ii)=luocc(4,ii)
     256                 :             :    end if
     257                 :             :  end do
     258                 :             : 
     259                 :             : !##########################################################################################################
     260                 :             : !####################################  Tests on input information  ########################################
     261                 :             : 
     262                 :             :  !Tests if we have enough data points (at least 3) to conduct distinct regression.
     263                 :           4 :  ndata=nfiles+1
     264                 :           4 :  write(std_out,'(a,i2,a)') ' Including unperturbed state, we have ',ndata,' data points.'
     265         [ -  + ]:           4 :  if (ndata==0) then
     266                 :           0 :    ABI_ERROR('No linear response data points found.')
     267         [ -  + ]:           4 :  else if (ndata==1) then
     268                 :             :    msg = sjoin('Only one data point found. This utility needs',ch10,&
     269                 :             :     'at least three (3) data points (two non-zero perturbations and one unperturbed) to compute',ch10,&
     270         [ #  # ]:           0 :     'the Hubbard parameter.')
     271                 :           0 :   ABI_ERROR(msg)
     272         [ -  + ]:           4 :  else if (ndata==2) then
     273                 :             :    msg = sjoin('Only two data points found. The scalar Hubbard Parameter from',ch10,&
     274                 :             :     'the two-point linear regression scheme has already been printed in your .abo file. Try bashing',ch10,&
     275         [ #  # ]:           0 :     '==>   grep "two-point regression" <run_name.abo> ',ch10,'to find the result of this calculation.')
     276                 :           0 :   ABI_ERROR(msg)
     277                 :             :  end if
     278                 :             : 
     279                 :             :  !pawujat consistency check.
     280   [ +  +  -  +  :          22 :  if (any(pawujat_file /= pawujat_file(1))) then
                   -  + ]
     281                 :             :    msg = sjoin("Found different values of pawujat in files: ", ltoa(pawujat_file),ch10,&
     282         [ #  # ]:           0 :          "Perturbed atom has to be consistent across perturbations to compute U or J.")
     283                 :           0 :   ABI_ERROR(msg)
     284                 :             :  end if
     285                 :             : 
     286                 :             :  !dmatpuopt consistency check
     287   [ +  +  -  +  :          22 :  if (any(dmatpuopt_file /= dmatpuopt_file(1))) then
                   -  + ]
     288                 :             :    msg = sjoin("Found different values of dmatpuopt in files: ", ltoa(dmatpuopt_file),ch10,&
     289         [ #  # ]:           0 :            "PAW projector must be consistent across perturbations to compute U or J.")
     290                 :           0 :   ABI_ERROR(msg)
     291                 :             :  end if
     292                 :             : 
     293                 :             :  !macro_uj consistency check
     294   [ +  +  -  +  :          22 :  if (any(macrouj_file /= macrouj_file(1))) then
                   -  + ]
     295                 :             :    msg = sjoin("Found different values of macro_uj in files: ",ltoa(macrouj_file),ch10,&
     296         [ #  # ]:           0 :            "Perturbation protocol and occupancy monitoring must be consistent to compute U or J.")
     297                 :           0 :   ABI_ERROR(msg)
     298                 :             :  end if
     299                 :             : 
     300                 :             :  !diemix/diemixmag consistency check
     301   [ +  +  -  +  :          22 :  if (any(diem_file /= diem_file(1))) then
                   -  + ]
     302                 :             :    msg = sjoin("Found different values of mixing constant in files: ",ltoa(diem_file),ch10,&
     303         [ #  # ]:           0 :           "Unscreened response functions will factor into U (J) incorrectly.")
     304                 :           0 :   ABI_ERROR(msg)
     305                 :             :  end if
     306                 :             : 
     307                 :             :  !Tests consistency of macro_uj, then writes message about macro_uj procedure selected.
     308                 :             :  !Also assigns Hubbard parameter-specific variables.
     309         [ -  + ]:           4 :  if (nspden==1) then
     310                 :           0 :    write(message,'(a)') ' Determination of U-parameter for unpolarized structure (non standard)'
     311         [ +  + ]:           4 :  else if (macro_uj==1.and.nspden==2) then
     312                 :           2 :    write(message,'(a)') ' Standard determination of the Hubbard U parameter.'
     313         [ -  + ]:           2 :  else if (macro_uj==2.and.nspden==2) then
     314                 :           0 :    write(message,'(a)') ' Determination of parameter on single spin channel (experimental)'
     315                 :           0 :    pertname='Pert. '
     316         [ -  + ]:           2 :  else if (macro_uj==3.and.nspden==2) then
     317                 :           0 :    parname='J'
     318                 :           0 :    pertname='Pert. '
     319                 :           0 :    write(message,'(a)') ' Determination of (not Hunds) J-parameter on single spin channel (experimental)'
     320         [ +  - ]:           2 :  else if (macro_uj==4.and.nspden==2) then
     321                 :           2 :    write(message,'(a)') ' Hunds J determination, implemented by L. MacEnulty August 2021'
     322                 :             :  end if
     323                 :           4 :  call wrtout(std_out,message)
     324                 :             : 
     325                 :             :  !Tests compatibility of nspden and macro_uj
     326         [ -  + ]:           4 :  if (macro_uj>1.and.nspden==1) then
     327                 :             :    msg = sjoin('U on a single spin channel (or J) can only be determined for nspden=2 ,',ch10,&
     328         [ #  # ]:           0 :     'Cannot calculate the chosen Hubbard parameter.')
     329                 :           0 :    ABI_ERROR(msg)
     330                 :             :  end if
     331                 :             : 
     332                 :             :  !Tests if perturbations are too small.
     333   [ +  -  -  +  :          26 :  if (maxval(abs(uj_perts))<0.00000001) then
          -  -  +  +  +  
                +  -  + ]
     334                 :             :    msg = sjoin('Perturbation magnitudes are too small.',ch10,&
     335         [ #  # ]:           0 :      'Rerun perturbative Abinit calculations with pawujv >> 1d-8.')
     336                 :           0 :    ABI_ERROR(msg)
     337                 :             :  end if
     338                 :             : 
     339                 :             : !##########################################################################################################
     340                 :             : !###############################  Calculation of the Response Functions  ##################################
     341                 :             : 
     342                 :             :  !Test compatibility of polynomial degree (if present as an argument) with
     343                 :             :  !number of data points. Otherwise, default to the following:
     344                 :             :  !If we have 3 data points, conduct at maximum a linear regression.
     345                 :             :  !If 4 data points, conduct linear and quadratic regressions.
     346                 :             :  !If more than 5 data points, conduct linear, quadratic and cubic regressions.
     347         [ -  + ]:           4 :  if (degarg/=1) then
     348         [ #  # ]:           0 :    if (degarg>ndata-2) then
     349                 :           0 :      write(std_out,'(4a,i2,3a,i2,2a)') ch10,' ERROR: Your chosen polynomial degree is too large. The resulting',ch10,&
     350                 :           0 : &       ' parameters will certainly be overfitted. Either conduct ',degarg+1,' perturbations,',ch10,&
     351                 :           0 : &       ' or execute this utility again with --d',ndata-2,' or smaller. Exiting program.',ch10
     352                 :           0 :      goto 100
     353                 :             :    else
     354                 :           0 :      mdegree=degarg
     355                 :             :    end if
     356                 :             :  else !Default max polynomial degree
     357         [ -  + ]:           4 :    if (ndata<=4) then
     358                 :           0 :      mdegree=ndata-2
     359                 :             :    else
     360                 :           4 :      mdegree=3
     361                 :             :    end if
     362                 :             :  end if
     363                 :           4 :  write(std_out,'(a,i2)') ' Maximum degree of polynomials analyzed: ',mdegree
     364                 :             : 
     365                 :             :  !Write warning about response matrices
     366                 :           4 :  write(std_out,'(5a)') ' NOTE: Unlike the ujdet utility, lruj treats the ',ch10,&
     367                 :           4 : ' response functions as scalars, not matrices!',ch10,&
     368                 :           8 : ' See lruj tutorial for more information.'
     369                 :             : 
     370                 :             :  !Allocate the response and error arrays
     371   [ +  -  -  +  :           4 :  ABI_MALLOC(chi0err,(mdegree))
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     372   [ +  -  -  +  :           4 :  ABI_MALLOC(chierr,(mdegree))
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     373   [ +  -  -  +  :           4 :  ABI_MALLOC(chi0,(mdegree))
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     374   [ +  -  -  +  :           4 :  ABI_MALLOC(chi,(mdegree))
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     375   [ +  -  -  +  :           4 :  ABI_MALLOC(hubpar,(mdegree))
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     376   [ +  -  -  +  :           4 :  ABI_MALLOC(hubparerr,(mdegree))
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     377                 :             : 
     378                 :             : !Start to write information in YAML format to plot with AbiPY
     379                 :           4 : ydoc = yamldoc_open('LRUJ_Abipy_Plots') !, width=11, real_fmt='(3f8.3)')
     380                 :           4 : call ydoc%add_int("natom",natom)
     381                 :           4 : call ydoc%add_int("ndata",ndata)
     382                 :           4 : call ydoc%add_int("pawujat",pawujat)
     383                 :           4 : call ydoc%add_int("macro_uj",macro_uj)
     384                 :           4 : call ydoc%add_string("diem_token",diem_token)
     385                 :           4 : call ydoc%add_real("diem",diem)
     386                 :             : 
     387                 :             :  !For all regressions, call subroutine to calculate polynomial fit for chi0 and chi.
     388         [ +  + ]:          16 :  do degree=1,mdegree
     389   [ +  -  +  -  :          12 :    ABI_MALLOC(chi0coeffs,(degree+1))
          -  +  -  +  -  
          +  -  +  -  +  
                   -  + ]
     390   [ +  -  +  -  :          12 :    ABI_MALLOC(chicoeffs,(degree+1))
          -  +  -  +  -  
          +  -  +  -  +  
                   -  + ]
     391                 :          12 :    call polynomial_regression(degree,ndata,perts,occs0,chi0coeffs,chi0err(degree))
     392                 :          12 :    call polynomial_regression(degree,ndata,perts,occs,chicoeffs,chierr(degree))
     393                 :             : 
     394                 :             :    !YAML doc information on regression coefficients
     395                 :          12 :    write(message, '(a,i0)' ) 'chi0_coefficients_degree',degree
     396                 :          12 :    call ydoc%add_real1d(message,chi0coeffs)
     397                 :          12 :    write(message, '(a,i0)' ) 'chi_coefficients_degree',degree
     398                 :          12 :    call ydoc%add_real1d(message,chicoeffs)
     399                 :             : 
     400                 :          12 :    chi0(degree)=chi0coeffs(2)/diem         !The derivative of all polynomial regressions
     401                 :          12 :    chi(degree)=chicoeffs(2)                !at pert=0.0 is just the second coefficient.
     402                 :          12 :    chi0err(degree)=chi0err(degree)/diem    !Chi0 error divided by diem also.
     403                 :          12 :    hubpar(degree)=signum*(1.0d0/chi0(degree)-1.0d0/chi(degree))
     404                 :          12 :    hubparerr(degree)=sqrt((chi0err(degree)/chi0(degree)**2)**2+(chierr(degree)/chi(degree)**2)**2)
     405         [ -  + ]:          12 :    ABI_FREE(chi0coeffs)
     406         [ -  + ]:          16 :    ABI_FREE(chicoeffs)
     407                 :             :  end do
     408                 :             : 
     409                 :             : !##########################################################################################################
     410                 :             : !#############################  Printing information on Hubbard Parameters ################################
     411                 :             : 
     412                 :             :  !Printing relevant information about the Hubbard parameter just calculated.
     413                 :           4 :  write(message,'(3a)') ch10,ch10, &
     414                 :           8 :    '*************************************************************************************************'
     415                 :           4 :  call wrtout(std_out,message)
     416                 :             :  write(message,'(4a)') &
     417                 :           4 :      '**************************************  Linear Response ',parname,'  **************************************',ch10
     418                 :           4 :  call wrtout(std_out,message)
     419                 :           4 :  write(message, '(a,i4)' ) ' Total number of atoms: ',natom
     420                 :           4 :  call wrtout(std_out,message)
     421                 :           4 :  write(message, '(a,i4)' ) ' Index of perturbed atom: ',pawujat
     422                 :           4 :  call wrtout(std_out,message)
     423                 :           4 :  write(message, '(a,i4)' ) ' Value of macro_uj:  ',macro_uj
     424                 :           4 :  call wrtout(std_out,message)
     425                 :           4 :  write(message, '(a,i4)' ) ' Value of dmatpuopt:  ',dmatpuopt
     426                 :           4 :  call wrtout(std_out,message)
     427                 :           4 :  write(message, '(a,f6.3)' ) ' Mixing constant factored out of Chi0:  ',diem
     428                 :           4 :  call wrtout(std_out,message)
     429                 :             :  write(message, '(a,f12.5,2a)' )&
     430                 :           4 :      ' Percentage of AE orbital within the PAW sphere of perturbed subspace: ',ph0phiint*100.00,'%',ch10
     431                 :           4 :  call wrtout(std_out,message)
     432                 :             : 
     433                 :           4 :  write(message, fmt='(10a)')'  Perturbations         ',occmag,ch10,&
     434                 :           4 : ' --------------- -----------------------------',ch10,&
     435         [ +  - ]:           4 : '    ',trim(pertname),' [eV]     Unscreened      Screened',ch10,&
     436                 :           8 : ' --------------- -----------------------------'
     437                 :           4 :  call wrtout(std_out,message)
     438         [ +  + ]:          22 :  do ipert=1,nfiles
     439         [ +  + ]:          18 :    if ((perts(ipert)>0.0d0).and.(perts(ipert-1)<0.0d0)) then
     440                 :           4 :      write(message, fmt='(3f15.10)') perts(0),occs0(0),occs(0)
     441                 :           4 :      call wrtout(std_out,message)
     442                 :             :    end if
     443                 :          18 :    write(message, fmt='(3f15.10)') perts(ipert),occs0(ipert),occs(ipert)
     444                 :          22 :    call wrtout(std_out,message)
     445                 :             :  end do
     446                 :             : 
     447                 :           4 :  write(message, fmt='(11a)') '                                                                       RMS Errors',&
     448                 :           4 :    ch10,'                                                         ---------------------------------------',ch10,&
     449                 :           4 :    ' Regression   Chi0 [eV^-1]   Chi [eV^-1]      ',parname,' [eV]    | Chi0 [eV^-1]  Chi [eV^-1]     ',parname,&
     450                 :           8 :    ' [eV]',ch10,'--------------------------------------------------------|---------------------------------------'
     451                 :           4 :  call wrtout(std_out,message)
     452         [ +  + ]:          16 :  do degree=1,mdegree
     453         [ +  + ]:          12 :    if (degree==1) then
     454                 :           4 :      regname=' Linear:    '
     455         [ +  + ]:           8 :    else if (degree==2) then
     456                 :           4 :      regname=' Quadratic: '
     457         [ +  - ]:           4 :    else if (degree==3) then
     458                 :           4 :      regname=' Cubic:     '
     459                 :             :    else
     460                 :           0 :      write(degreename,'(i2)') degree
     461   [ #  #  #  # ]:           0 :      regname=' Degree'//trim(degreename)//' : '
     462                 :             :    end if
     463                 :          12 :    write(message,fmt='(a,3f14.7,a,3f13.7)') regname,chi0(degree),chi(degree),hubpar(degree),&
     464                 :          24 :      '  |',chi0err(degree),chierr(degree),hubparerr(degree)
     465                 :          16 :    call wrtout(std_out,message)
     466                 :             :  end do
     467                 :             : 
     468                 :             :  write(message,'(3a)') &
     469                 :           4 :    '*************************************************************************************************',ch10,&
     470                 :           8 :    '*************************************************************************************************'
     471                 :           4 :  call wrtout(std_out,message)
     472                 :             : 
     473                 :             : 
     474                 :             : !##########################################################################################################
     475                 :             : !############################################  Deallocations ##############################################
     476                 :             : 
     477                 :             : 
     478         [ -  + ]:           4 :  ABI_FREE(perts)
     479         [ -  + ]:           4 :  ABI_FREE(occs0)
     480         [ -  + ]:           4 :  ABI_FREE(occs)
     481         [ -  + ]:           4 :  ABI_FREE(luocc_nnat)
     482         [ -  + ]:           4 :  ABI_FREE(pawujat_file)
     483         [ -  + ]:           4 :  ABI_FREE(diem_file)
     484         [ -  + ]:           4 :  ABI_FREE(dmatpuopt_file)
     485         [ -  + ]:           4 :  ABI_FREE(ph0phiint_file)
     486         [ -  + ]:           4 :  ABI_FREE(macrouj_file)
     487         [ -  + ]:           4 :  ABI_FREE(nspden_file)
     488         [ -  + ]:           4 :  ABI_FREE(chi0err)
     489         [ -  + ]:           4 :  ABI_FREE(chierr)
     490         [ -  + ]:           4 :  ABI_FREE(chi0)
     491         [ -  + ]:           4 :  ABI_FREE(chi)
     492         [ -  + ]:           4 :  ABI_FREE(hubpar)
     493         [ -  + ]:           4 :  ABI_FREE(hubparerr)
     494         [ -  + ]:           4 :  ABI_FREE(luocc)
     495         [ -  + ]:           4 :  ABI_FREE(uj_perts)
     496         [ -  + ]:           4 :  ABI_FREE(file_paths)
     497                 :             : 
     498                 :             :  !Ending herald.
     499                 :           4 :  write(std_out,*) ch10,'Linear Response UJ (LRUJ) program complete. Live long and prosper. ~LMac',ch10
     500                 :             : 
     501                 :           4 :  call ydoc%write_and_free(std_out)
     502                 :             : 
     503                 :             :  ! Writes information on file about the memory before ending mpi module, if memory profiling is enabled
     504                 :           4 :  call abinit_doctor("__lruj")
     505                 :             : 
     506                 :           4 :  100 call xmpi_end()
     507                 :             : 
     508                 :             : !##########################################################################################################
     509                 :             : !#####################################  Subroutines and Functions  ########################################
     510                 :             : 
     511                 :             : contains
     512                 :             : 
     513                 :             : !  Show command line help
     514                 :           0 : subroutine lruj_show_help()
     515                 :             : 
     516                 :           0 :   write(std_out,"(a)")" "
     517                 :           0 :   write(std_out,"(a)")"           Linear Response Hubbard U and Hund's J (LRUJ) Utility"
     518                 :           0 :   write(std_out,"(a)")"-----------------------------------------------------------------------------"
     519                 :           0 :   write(std_out,"(a)")"To execute the LRUJ utility, execute: "
     520                 :           0 :   write(std_out,"(a)")"   ./lruj  FILE1 FILE2 FILE3 ... [options]"
     521                 :           0 :   write(std_out,"(2a)")"             ^ input files must be _LRUJ.nc from Abinit run",ch10
     522                 :           0 :   write(std_out,"(a)")" --version              Show version number and exit."
     523                 :           0 :   write(std_out,"(a)")" -h, --help             Show this help and exit."
     524                 :           0 :   write(std_out,"(a)")" --d <n>                Set the maximum degree n polynomial calculated for"
     525                 :           0 :   write(std_out,"(a)")"                           the response functions chi and chi0."
     526                 :           0 :   write(std_out,"(a)")"                           (i.e., 1=linear, 2=quadratic, 3=cubic, etc.)"
     527                 :           0 :   write(std_out,"(a)")"                           NOTE: a degree n polynomial will require at minimum"
     528                 :           0 :   write(std_out,"(a)")"                           n+2 points (n+1 perturbations and the unperturbed"
     529                 :           0 :   write(std_out,"(a)")"                           case) or more so as to avoid overfitting."
     530                 :             : 
     531                 :           4 : end subroutine lruj_show_help
     532                 :             : 
     533                 :             : ! Function to simplify reading in of variables from netcdf files.
     534                 :         144 : integer function vid(vname)
     535                 :             :   character(len=*),intent(in) :: vname
     536                 :         288 :   vid = nctk_idname(ncid, vname)
     537                 :         144 : end function vid
     538                 :             : 
     539                 :             : end program lruj
     540                 :             : !!***
        

Generated by: LCOV version 2.3-1