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-09-21 19:39:32 Functions: 100.0 % 4 4

            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