LCOV - code coverage report
Current view: top level - src/77_ddb - m_anaddb_driver.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 91.3 % 415 379
Test Date: 2026-09-19 17:42:43 Functions: 90.9 % 22 20

            Line data    Source code
       1              : !!****m*ABINIT/m_anaddb_driver
       2              : !! NAME
       3              : !!  m_anaddb_driver
       4              : !!
       5              : !! FUNCTION
       6              : !!
       7              : !! COPYRIGHT
       8              : !!  Copyright (C) 2014-2026 ABINIT group (GA)
       9              : !!  This file is distributed under the terms of the
      10              : !!  GNU General Public License, see ~abinit/COPYING
      11              : !!  or http://www.gnu.org/copyleft/gpl.txt .
      12              : !!
      13              : !! SOURCE
      14              : 
      15              : #if defined HAVE_CONFIG_H
      16              : #include "config.h"
      17              : #endif
      18              : 
      19              : #include "abi_common.h"
      20              : 
      21              : module m_anaddb_driver
      22              : 
      23              :  use defs_basis
      24              :  use m_abicore
      25              :  use m_xmpi
      26              :  use m_errors
      27              :  use m_nctk
      28              :  use netcdf
      29              :  use m_ifc
      30              :  use m_ddb_hdr
      31              :  use m_phonons
      32              :  use m_supercell
      33              :  use m_raman
      34              : 
      35              :  use m_fstrings,       only : strcat
      36              :  use m_crystal,        only : crystal_t
      37              :  use m_anaddb_dataset, only : anaddb_dataset_type
      38              :  use m_ddb,            only : ddb_type, asrq0_t
      39              :  use m_dynmat,         only : gtdyn9, dfpt_phfrq, dfpt_prtph
      40              :  use m_ddb_interpolate, only : ddb_interpolate
      41              :  use m_harmonic_thermo, only : harmonic_thermo
      42              :  use m_elphon,         only : elphon
      43              :  use m_thmeig,         only : thmeig
      44              :  use m_relaxpol,       only : relaxpol
      45              :  use m_ddb_diel,       only : ddb_diel
      46              :  use m_ddb_elast,      only : ddb_elast
      47              :  use m_ddb_piezo,      only : ddb_piezo
      48              :  use m_ddb_internalstr, only : ddb_internalstr
      49              :  use m_gruneisen,      only : gruns_anaddb
      50              :  use m_ddb_flexo,      only : ddb_flexo, ddb_phi1
      51              :  use m_lwf,            only : run_lattice_wannier
      52              : 
      53              :  implicit none
      54              : 
      55              :  private
      56              : 
      57              :  public:: anaddb_driver_type
      58              : 
      59              : !----------------------------------------------------------------------
      60              : 
      61              : !!****t* m_anaddb_driver/anaddb_driver_type
      62              : !! NAME
      63              : !! anaddb_driver_type
      64              : !!
      65              : !! FUNCTION
      66              : !! The anaddb_driver_type structured datatype
      67              : !! Main subroutines run by anaddb.
      68              : !!
      69              : !! SOURCE
      70              : 
      71              :  type anaddb_driver_type
      72              : 
      73              :    integer:: natom
      74              :    integer:: msize
      75              :    integer:: mpert
      76              : 
      77              :    logical:: do_ifc=.false.
      78              :    logical:: do_electric_tensors=.false.
      79              :    logical:: do_dielectric_q0=.false.
      80              :    logical:: do_dielectric_nonana=.false.
      81              :    logical:: do_phonon_dos=.false.
      82              :    logical:: do_phonon_bs=.false.
      83              : 
      84              :    real(dp):: epsinf(3, 3)
      85              :    real(dp):: dchide(3,3,3)
      86              :    real(dp):: dielt_rlx(3, 3)
      87              :    real(dp):: elast(6, 6)
      88              : 
      89              :    real(dp), allocatable:: d2cart(:,:)
      90              :    ! d2cart(2,msize)
      91              : 
      92              :    real(dp), allocatable:: displ(:)
      93              :    ! displ(2*3*natom*3*natom)
      94              : 
      95              :    real(dp), allocatable:: phfrq(:)
      96              :    ! phfrq(3*natom)
      97              : 
      98              :    real(dp), allocatable:: instrain(:,:)
      99              :    ! instrain(3*natom,6)
     100              : 
     101              :    real(dp), allocatable:: dchidt(:,:,:,:)
     102              :    ! dchidt(natom,3,3,3)
     103              : 
     104              :    real(dp), allocatable:: fact_oscstr(:,:,:)
     105              :    ! fact_oscstr(2,3,3*natom)
     106              : 
     107              :    real(dp), allocatable:: zeff(:,:,:)
     108              :    ! zeff(3,3,natom)
     109              : 
     110              :    real(dp), allocatable:: qdrp_cart(:,:,:,:)
     111              :    ! qdrp_cart(3,3,3,natom)
     112              : 
     113              :    real(dp), allocatable:: dcdq(:,:,:,:,:)
     114              :    ! dcdq(3,natom,3,natom,3)
     115              : 
     116              :    real(dp), allocatable:: dcdqdq(:,:,:,:,:)
     117              :    ! dcdqdq(3,natom,3,3,3)
     118              : 
     119              :  contains
     120              : 
     121              :    procedure :: init => anaddb_driver_init
     122              :    ! Initialize object
     123              : 
     124              :    procedure :: free => anaddb_driver_free
     125              :    ! Free memory
     126              : 
     127              :    procedure :: open_write_nc => anaddb_driver_open_write_nc
     128              :    ! Open netcdf output and write some info
     129              : 
     130              :    procedure :: electric_tensors => anaddb_driver_electric_tensors
     131              :    ! Compute dielectric tensor, born effective charges, and quadrupoles
     132              : 
     133              :    procedure :: structural_response => anaddb_driver_structural_response
     134              :    ! Structural response at fixed polarization
     135              : 
     136              :    procedure :: susceptibilities => anaddb_driver_susceptibilities
     137              :    ! Compute non-linear optical susceptibilities and first-order derivatives
     138              : 
     139              :    procedure :: interatomic_force_constants => anaddb_driver_interatomic_force_constants
     140              :    ! Compute the interatomic force constants from a ddb
     141              : 
     142              :    procedure :: phdos => anaddb_driver_phdos
     143              :    ! Compute phonon density of states
     144              : 
     145              :    procedure :: thermal_supercell => anaddb_driver_thermal_supercell
     146              :    ! Thermal supercell calculation
     147              : 
     148              :    procedure :: harmonic_thermo => anaddb_driver_harmonic_thermo
     149              :    ! Phonon density of states and thermodynamical properties
     150              : 
     151              :    procedure :: dielectric_q0 => anaddb_driver_dielectric_q0
     152              :    ! Dielectric tensor and related properties
     153              : 
     154              :    procedure :: nonlinear_response => anaddb_driver_nonlinear_response
     155              :    ! Non-linear response: electrooptic and Raman
     156              : 
     157              :    procedure :: dielectric_nonana => anaddb_driver_dielectric_nonana
     158              :    ! Non-analyticity in the dielectric matrix and raman susceptibility
     159              : 
     160              :    procedure :: internal_strain => anaddb_driver_internal_strain
     161              :    ! Internal strain
     162              : 
     163              :    procedure :: elastic_tensor => anaddb_driver_elastic_tensor
     164              :    ! Elastic tensor
     165              : 
     166              :    procedure :: piezoelectric_tensor => anaddb_driver_piezoelectric_tensor
     167              :    ! Piezoelectric tensor
     168              : 
     169              :    procedure :: flexoelectric_tensor => anaddb_driver_flexoelectric_tensor
     170              :    ! Flexoelectric tensor
     171              : 
     172              :    procedure :: get_dcdq => anaddb_driver_get_dcdq
     173              :    ! Get IFCs derivatives for the imposition of rotational invariance
     174              : 
     175              :    procedure :: lattice_wannier => anaddb_driver_lattice_wannier
     176              :    ! Construct the Lattice Wannier functions
     177              : 
     178              :    procedure :: convertdim_dielt => anaddb_driver_convertdim_dielt
     179              :    ! Extract low-dimmensional dielectric response from periodic calculations
     180              : 
     181              :  end type anaddb_driver_type
     182              : !!***
     183              : 
     184              : contains
     185              : 
     186              : !!****f* m_anaddb_driver/anaddb_driver_init
     187              : !! NAME
     188              : !! anaddb_driver_init
     189              : !!
     190              : !! FUNCTION
     191              : !! Initialize object
     192              : !!
     193              : !! INPUTS
     194              : !!
     195              : !! OUTPUT
     196              : !!
     197              : !! SOURCE
     198              : 
     199           81 : subroutine anaddb_driver_init(driver, dtset)
     200              : 
     201              : !Arguments -------------------------------
     202              :  class(anaddb_driver_type), intent(inout):: driver
     203              :  type(anaddb_dataset_type), intent(in):: dtset
     204              : ! ************************************************************************
     205              : 
     206              :  ! Set control flags
     207           81 :  if (dtset%ifcflag == 1) then
     208           55 :    driver%do_ifc = .true.
     209              :  end if
     210              : 
     211              :  if (dtset%ifcflag /= 0 .or. dtset%dieflag /= 0 &
     212              : &    .or. dtset%dipdip /= 0 .or. dtset%dipquad /= 0 .or. dtset%quadquad /= 0 &
     213              : &    .or. dtset%nph2l /= 0 .or. dtset%nlflag /= 0 &
     214              : &    .or. dtset%piezoflag /= 0 .or. dtset%flexoflag /= 0 &
     215           81 : &    .or. dtset%polflag /= 0) then
     216           77 :    driver%do_electric_tensors = .true.
     217              :  end if
     218              : 
     219              :  if ((dtset%dieflag /= 0 .and. dtset%dieflag /= 2) &
     220              : &    .or. dtset%nph2l /= 0 .or. dtset%nlflag == 1 &
     221           81 : &    .or. dtset%piezoflag /= 0) then
     222           27 :    driver%do_dielectric_q0 = .true.
     223              :  end if
     224              : 
     225           81 :  if (dtset%nph2l /= 0) then
     226           24 :    driver%do_dielectric_nonana = .true.
     227              :  end if
     228              : 
     229           81 :  if (dtset%ifcflag == 1 .and. any(dtset%prtdos==[1, 2])) then
     230           11 :    driver%do_phonon_dos = .true.
     231              :  end if
     232              : 
     233           81 :  if (dtset%nph1l /= 0 .or. dtset%nqpath /= 0) then
     234           66 :    driver%do_phonon_bs = .true.
     235              :  end if
     236              : 
     237           81 :  if (dtset%gruns_nddbs /= 0) then
     238            1 :    driver%do_ifc = .false.
     239            1 :    driver%do_electric_tensors = .false.
     240            1 :    driver%do_dielectric_q0 = .false.
     241            1 :    driver%do_dielectric_nonana = .false.
     242            1 :    driver%do_phonon_bs = .false.
     243            1 :    driver%do_phonon_dos = .false.
     244              :  end if
     245              : 
     246              :  ! Copy dimensions
     247           81 :  driver%natom = dtset%natom
     248           81 :  driver%msize = dtset%msize
     249           81 :  driver%mpert = dtset%mpert
     250              : 
     251              :  ! Allocate memory
     252          243 :  ABI_MALLOC(driver%d2cart, (2, driver%msize))
     253          243 :  ABI_MALLOC(driver%displ, (2*3*driver%natom*3*driver%natom))
     254          243 :  ABI_MALLOC(driver%phfrq, (3*driver%natom))
     255          324 :  ABI_MALLOC(driver%instrain, (3*driver%natom, 6))
     256          486 :  ABI_MALLOC(driver%dcdq, (3, driver%natom, 3, driver%natom, 3))
     257          405 :  ABI_MALLOC(driver%dcdqdq, (3, driver%natom, 3, 3, 3))
     258        50820 :  driver%dcdq = zero
     259        31320 :  driver%dcdqdq = zero
     260              :  ! Electric tensors
     261          243 :  ABI_MALLOC(driver%zeff, (3, 3, driver%natom))
     262          243 :  ABI_MALLOC(driver%qdrp_cart, (3, 3, 3, driver%natom))
     263              : 
     264              :  ! oscillator strength and Lyddane-Sachs-Teller relation
     265          162 :  ABI_MALLOC(driver%fact_oscstr, (2, 3, 3*driver%natom))
     266              : 
     267              :  ! Susceptibilities
     268           81 :  if (dtset%nlflag > 0) then
     269            8 :    ABI_MALLOC(driver%dchidt, (driver%natom, 3, 3, 3))
     270              :  end if
     271              : 
     272           81 : end subroutine anaddb_driver_init
     273              : !!***
     274              : 
     275              : 
     276              : !!****f* m_anaddb_driver/anaddb_driver_free
     277              : !! NAME
     278              : !! anaddb_driver_free
     279              : !!
     280              : !! FUNCTION
     281              : !! Deallocate memory
     282              : !!
     283              : !! INPUTS
     284              : !!
     285              : !! OUTPUT
     286              : !!
     287              : !! SOURCE
     288              : 
     289           81 : subroutine anaddb_driver_free(driver)
     290              : 
     291              : !Arguments -------------------------------
     292              :  class(anaddb_driver_type), intent(inout):: driver
     293              : ! ************************************************************************
     294              : 
     295           81 :  ABI_SFREE(driver%zeff)
     296           81 :  ABI_SFREE(driver%qdrp_cart)
     297           81 :  ABI_SFREE(driver%d2cart)
     298           81 :  ABI_SFREE(driver%displ)
     299           81 :  ABI_SFREE(driver%phfrq)
     300           81 :  ABI_SFREE(driver%dchidt)
     301           81 :  ABI_SFREE(driver%instrain)
     302           81 :  ABI_SFREE(driver%fact_oscstr)
     303           81 :  ABI_SFREE(driver%dcdq)
     304           81 :  ABI_SFREE(driver%dcdqdq)
     305              : 
     306           81 : end subroutine anaddb_driver_free
     307              : !!***
     308              : 
     309              : !!****f* m_anaddb_driver/anaddb_driver_open_write_nc
     310              : !! NAME
     311              : !! anaddb_driver_open_write_nc
     312              : !!
     313              : !! FUNCTION
     314              : !! Open anaddb netcdf output and define dimensions.
     315              : !!
     316              : !! INPUTS
     317              : !!
     318              : !! OUTPUT
     319              : !!
     320              : !! SOURCE
     321              : 
     322           81 : subroutine anaddb_driver_open_write_nc(driver, ana_ncid, dtset, crystal, comm)
     323              : 
     324              : !Arguments -------------------------------
     325              :  class(anaddb_driver_type), intent(inout):: driver
     326              :  type(anaddb_dataset_type), intent(in):: dtset
     327              :  type(crystal_t),intent(in):: crystal
     328              :  integer,intent(in):: comm
     329              :  integer, intent(out):: ana_ncid
     330              : 
     331              : !Local variables -------------------------------
     332              :  integer, parameter:: master = 0
     333              :  integer:: natom,lenstr
     334              :  integer:: ncerr
     335              :  integer:: my_rank
     336              : ! ************************************************************************
     337              : 
     338           81 :  my_rank = xmpi_comm_rank(comm)
     339              : 
     340           81 :  natom = driver%natom
     341           81 :  lenstr = dtset%lenstr
     342              : 
     343              :  ! Open the netcdf file that will contain the anaddb results
     344           81 :  ana_ncid = nctk_noid
     345           81 :  if (my_rank == master) then
     346           81 :    NCF_CHECK_MSG(nctk_open_create(ana_ncid, trim(dtset%prefix_outdata)//"_anaddb.nc", xmpi_comm_self), "Creating anaddb.nc")
     347              :    ncerr = nctk_def_dims(ana_ncid, [ &
     348              :        nctkdim_t('number_of_atoms', natom), &
     349              :        nctkdim_t('natom3', 3*natom), &
     350              :        nctkdim_t('number_of_phonon_modes', 3*natom), &
     351              :        nctkdim_t('anaddb_input_len', lenstr) &
     352          405 :    ], defmode=.True.)
     353           81 :    NCF_CHECK(ncerr)
     354              :    ncerr = nctk_def_arrays(ana_ncid, [ &
     355              :      nctkarr_t("anaddb_input_string", "char", "anaddb_input_len") &
     356          162 :    ])
     357           81 :    NCF_CHECK(ncerr)
     358              :    !NCF_CHECK(nctk_defnwrite_ivars(ana_ncid, ["anaddb_version"], [1]))
     359              : 
     360              :    ncerr = nctk_def_iscalars(ana_ncid, [character(len = nctk_slen) :: &
     361          567 :        "asr", "chneut", "dipdip", "symdynmat", "dipquad", "quadquad"])
     362           81 :    NCF_CHECK(ncerr)
     363              : 
     364           81 :    NCF_CHECK(nctk_set_datamode(ana_ncid))
     365           81 :    ncerr = nf90_put_var(ana_ncid, nctk_idname(ana_ncid, "anaddb_input_string"), dtset%input_string(:lenstr))
     366           81 :    NCF_CHECK(ncerr)
     367           81 :    NCF_CHECK(crystal%ncwrite(ana_ncid))
     368              : 
     369              :    ncerr = nctk_write_iscalars(ana_ncid, [character(len = nctk_slen) :: &
     370              :      "asr", "chneut", "dipdip", "symdynmat", "dipquad", "quadquad"], &
     371              :      [dtset%asr, dtset%chneut, dtset%dipdip, &
     372         1053 :       dtset%symdynmat, dtset%dipquad, dtset%quadquad])
     373           81 :    NCF_CHECK(ncerr)
     374              :  end if
     375              : 
     376           81 : end subroutine anaddb_driver_open_write_nc
     377              : !!***
     378              : 
     379              : !!****f* m_anaddb_driver/anaddb_driver_electric_tensors
     380              : !! NAME
     381              : !! anaddb_driver_electric_tensors
     382              : !!
     383              : !! FUNCTION
     384              : !! get Dielectric tensor, born effective charges, and quadrupole tensor,
     385              : !! and write them to netcdf output.
     386              : !!
     387              : !! INPUTS
     388              : !!
     389              : !! OUTPUT
     390              : !!
     391              : !! SOURCE
     392              : 
     393           76 : subroutine anaddb_driver_electric_tensors(driver, dtset, crystal, ddb, ddb_lw, ddb_hdr, ana_ncid, comm)
     394              : 
     395              : !Arguments -------------------------------
     396              :  class(anaddb_driver_type), intent(inout):: driver
     397              :  type(anaddb_dataset_type), intent(inout):: dtset
     398              :  type(crystal_t), intent(in):: crystal
     399              :  type(ddb_type), intent(inout):: ddb
     400              :  type(ddb_type), intent(inout):: ddb_lw
     401              :  type(ddb_hdr_type), intent(in):: ddb_hdr
     402              :  integer, intent(in):: ana_ncid
     403              :  integer, intent(in):: comm
     404              : 
     405              : !Local variables -------------------------------
     406              :  integer, parameter:: master = 0
     407              :  integer:: my_rank
     408              :  integer:: ii
     409              :  integer:: iblok, iblok_quadrupoles, iblok_epsinf
     410              :  integer:: ncerr
     411              :  integer:: lwsym
     412              :  character(len = 500):: msg
     413              :  integer:: units(2)
     414              : ! ************************************************************************
     415              : 
     416          228 :  units = [std_out, ab_out]
     417              : 
     418              :  ! Get Quadrupole tensor
     419           76 :  iblok_quadrupoles = 0
     420         9596 :  driver%qdrp_cart = zero
     421           76 :  if (ddb_hdr%has_d3E_lw) then
     422          648 :    write(msg, '(2a, (80a), 2a)') ch10, ('=',ii = 1, 80)
     423            8 :    call wrtout(units, msg)
     424            8 :    lwsym = 1
     425            8 :    iblok_quadrupoles = ddb_lw%get_quadrupoles(ddb_hdr%ddb_version, lwsym, BLKTYP_d3E_lw, driver%qdrp_cart)
     426              :  end if
     427              : 
     428              :  ! Get the electronic dielectric tensor (epsinf) and Born effective charges (zeff)
     429              :  ! (initialized to one_3D and zero if the derivatives are not available in the DDB file)
     430           76 :  iblok = ddb%get_dielt_zeff(crystal, dtset%rfmeth, dtset%chneut, dtset%selectz, driver%epsinf, driver%zeff)
     431              : 
     432              :  ! Try to get epsinf, in case just the DDE are present
     433           76 :  if (iblok == 0) then
     434           32 :    iblok_epsinf = ddb%get_dielt(dtset%rfmeth, driver%epsinf)
     435              :  end if
     436              : 
     437              :  !if (iblok_epsinf == 0) then
     438              :  !GA: Not the greatest way of checking
     439           76 :  if (driver%epsinf(1, 1)==one .and. driver%epsinf(2, 2)==one .and. driver%epsinf(3, 3)==one) then
     440           33 :    write(msg, '(5a)') ch10, &
     441           33 :      ' The DDB file does not contain the derivatives w.r.t. electric field perturbation. ',ch10, &
     442           66 :      ' The program will continue by setting the electronic dielectric tensor to 1. ',ch10
     443              :   ! call wrtout([ab_out], msg)
     444           33 :    ABI_WARNING(msg)
     445              :  end if
     446              : 
     447              : !**********************************************************************
     448              : ! Write Dielectric tensor, born effective charges, and quadrupoles to netcdf output.
     449              : 
     450           76 :  my_rank = xmpi_comm_rank(comm)
     451           76 :  if (my_rank == master) then
     452              :    ncerr = nctk_def_arrays(ana_ncid, [&
     453              :    nctkarr_t('emacro_cart', "dp", 'number_of_cartesian_directions, number_of_cartesian_directions'), &
     454              :    nctkarr_t('quadrupoles_cart', "dp", 'three, three, three, number_of_atoms'), &
     455              :    nctkarr_t('becs_cart', "dp", "number_of_cartesian_directions, number_of_cartesian_directions, number_of_atoms")],&
     456          304 :    defmode=.True.)
     457           76 :    NCF_CHECK(ncerr)
     458              : 
     459           76 :    NCF_CHECK(nctk_set_datamode(ana_ncid))
     460           76 :    NCF_CHECK(nf90_put_var(ana_ncid, nctk_idname(ana_ncid, 'emacro_cart'), driver%epsinf))
     461           76 :    NCF_CHECK(nf90_put_var(ana_ncid, nctk_idname(ana_ncid, 'quadrupoles_cart'), driver%qdrp_cart))
     462           76 :    NCF_CHECK(nf90_put_var(ana_ncid, nctk_idname(ana_ncid, 'becs_cart'), driver%zeff))
     463              :  end if
     464              : 
     465           76 : end subroutine anaddb_driver_electric_tensors
     466              : !!***
     467              : 
     468              : !!****f* m_anaddb_driver/anaddb_driver_structural_response
     469              : !! NAME
     470              : !! anaddb_driver_structural_response
     471              : !!
     472              : !! FUNCTION
     473              : !! Compute structural response at fixed polarization
     474              : !!
     475              : !! INPUTS
     476              : !!
     477              : !! OUTPUT
     478              : !!
     479              : !! SOURCE
     480              : 
     481            3 : subroutine anaddb_driver_structural_response(driver, dtset, crystal, ddb)
     482              : 
     483              : !Arguments -------------------------------
     484              :  class(anaddb_driver_type), intent(inout):: driver
     485              :  type(anaddb_dataset_type), intent(in):: dtset
     486              :  type(crystal_t), intent(in):: crystal
     487              :  type(ddb_type), intent(inout):: ddb
     488              : 
     489              : !Local variables -------------------------------
     490              :  integer:: iblok
     491              :  integer:: msize
     492              :  real(dp):: etotal
     493              :  character(len = 500):: msg
     494              :  integer:: rfelfd(4), rfphon(4), rfstrs(4)
     495              :  real(dp):: red_ptot(3)
     496              :  real(dp):: pel(3)
     497              :  real(dp):: strten(6)
     498              :  real(dp) :: targetpol(3)
     499              :  real(dp):: qphnrm(3), qphon(3, 3)
     500            3 :  integer, allocatable:: d2flg(:)
     501            3 :  real(dp), allocatable:: gred(:,:)
     502              : ! ************************************************************************
     503              : 
     504            3 :  msize = dtset%msize
     505            9 :  ABI_MALLOC(d2flg, (msize))
     506              : 
     507              :  ! Look for the Gamma Block in the DDB
     508           12 :  qphon(:,1)=zero
     509            3 :  qphnrm(1)=zero
     510            9 :  rfphon(1:2)=1
     511            9 :  rfelfd(1:2)=2
     512            9 :  rfstrs(1:2)=0
     513              : 
     514              :  !write(std_out,*)"ddb%mpert",ddb%mpert
     515            3 :  call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, dtset%rfmeth)
     516              :  !iblok = ddb%get_dielt_zeff(crystal, dtset%rfmeth, dtset%chneut, dtset%selectz, driver%epsinf, driver%zeff)
     517              : 
     518            3 :  if(iblok /= 0)then
     519              :    ! Save the second-order derivatives
     520        17984 :    driver%d2cart(1:2, 1:msize) = ddb%val(1:2, 1:msize, iblok)
     521         5996 :    d2flg(1:msize) = ddb%flg(1:msize, iblok)
     522              : 
     523              :  else
     524              :    ! the gamma blok has not been found
     525            1 :    if (dtset%relaxat == 0 .and. dtset%relaxstr == 0) then
     526              :      ! The gamma blok is not needed
     527         6076 :      driver%d2cart(1:2, 1:msize)=zero
     528         2026 :      d2flg(1:msize)=1
     529              :    else
     530              :      ! There is a problem !
     531              :      write(msg, '(7a)' )&
     532            0 :       'The dynamical matrix at Gamma is needed, in order to perform ',ch10, &
     533            0 :       "relaxation at constant polarisation (Na Sai's method)",ch10, &
     534            0 :       'However, this was not found in the DDB.',ch10, &
     535            0 :       'Action: complete your DDB with the dynamical matrix at Gamma.'
     536            0 :      ABI_ERROR(msg)
     537              :    end if
     538              :  end if  ! iblok not found
     539              : 
     540              :  ! Extract the block with the total energy
     541            3 :  if (ddb%get_etotal(etotal) == 0) then
     542            0 :    ABI_ERROR("DDB file does not contain GS etotal")
     543              :  end if
     544              : 
     545              :  ! Extract the polarizability
     546            3 :  iblok = ddb%get_pel(pel, dtset%relaxat, dtset%relaxstr)
     547              : 
     548              :  ! Extract the forces
     549            3 :  iblok = ddb%get_gred(gred, dtset%relaxat, dtset%relaxstr)
     550              : 
     551              :  ! Extract the stress tensor
     552            3 :  iblok = ddb%get_strten(strten, dtset%relaxat, dtset%relaxstr)
     553              : 
     554              :  ! when called from here red_ptot is not set  ! So set it to zero
     555            3 :  red_ptot(:) = zero
     556              : 
     557           12 :  targetpol(:) = dtset%targetpol
     558              : 
     559              :  call relaxpol(crystal, d2flg, driver%d2cart, etotal, gred, dtset%iatfix, &
     560              : &   ab_out, dtset%istrfix, dtset%mpert, dtset%msize, dtset%natfix, crystal%natom, &
     561              : &   dtset%nstrfix, pel, red_ptot, dtset%relaxat, dtset%relaxstr, &
     562            3 : &   strten, targetpol)
     563              : 
     564            3 :  ABI_SFREE(gred)
     565            3 :  ABI_FREE(d2flg)
     566              : 
     567            3 : end subroutine anaddb_driver_structural_response
     568              : !!***
     569              : 
     570              : !!****f* m_anaddb_driver/anaddb_driver_susceptibilities
     571              : !! NAME
     572              : !! anaddb_driver_susceptibilities
     573              : !!
     574              : !! FUNCTION
     575              : !! Compute non-linear optical susceptibilities,
     576              : !! and if dtset%nlflag < 3, compute first-order change
     577              : !! in the linear dielectric susceptibility induced by an atomic displacement.
     578              : !! Then write susceptibilites to netcdf output.
     579              : !!
     580              : !! INPUTS
     581              : !!
     582              : !! OUTPUT
     583              : !!
     584              : !! SOURCE
     585              : 
     586            4 : subroutine anaddb_driver_susceptibilities(driver, dtset, ddb, ana_ncid, comm)
     587              : 
     588              : !Arguments -------------------------------
     589              :  class(anaddb_driver_type), intent(inout):: driver
     590              :  type(anaddb_dataset_type), intent(in):: dtset
     591              :  type(ddb_type), intent(in):: ddb
     592              :  integer, intent(in):: ana_ncid
     593              :  integer, intent(in):: comm
     594              : 
     595              : !Local variables -------------------------------
     596              :  integer, parameter:: master = 0
     597              :  integer:: my_rank
     598              :  integer:: ncerr
     599              : ! ************************************************************************
     600              : 
     601            4 :  if (ddb%get_dchidet(dtset%ramansr, dtset%nlflag, driver%dchide, driver%dchidt) == 0) then
     602            0 :    ABI_ERROR("Cannot find block corresponding to non-linear optical susceptibilities in DDB file")
     603              :  end if
     604              : 
     605              :  ! Save to the netcdf
     606            4 :  my_rank = xmpi_comm_rank(comm)
     607            4 :  if (my_rank == master) then
     608            8 :    ncerr = nctk_def_arrays(ana_ncid, [nctkarr_t("dchide", "dp", "three, three, three")], defmode=.True.)
     609            4 :    NCF_CHECK(ncerr)
     610            4 :    NCF_CHECK(nctk_set_datamode(ana_ncid))
     611            4 :    NCF_CHECK(nf90_put_var(ana_ncid, nctk_idname(ana_ncid, "dchide"), driver%dchide))
     612              : 
     613              :    ! dchidt only present if nlflag == 1 or 2
     614            4 :    if (dtset%nlflag < 3) then
     615              :      ncerr = nctk_def_arrays(ana_ncid, [nctkarr_t("dchidt", "dp", &
     616            6 :      "number_of_atoms, three, three, three")], defmode=.True.)
     617            3 :      NCF_CHECK(ncerr)
     618            3 :      NCF_CHECK(nctk_set_datamode(ana_ncid))
     619            3 :      NCF_CHECK(nf90_put_var(ana_ncid, nctk_idname(ana_ncid, "dchidt"), driver%dchidt))
     620              :    end if
     621              :  end if
     622              : 
     623            4 : end subroutine anaddb_driver_susceptibilities
     624              : !!***
     625              : 
     626              : !!****f* m_anaddb_driver/anaddb_driver_interatomic_force_constants
     627              : !! NAME
     628              : !! anaddb_driver_interatomic_force_constants
     629              : !!
     630              : !! FUNCTION
     631              : !! Interatomic forces calculation
     632              : !! Compute the interatomic force constants from a ddb.
     633              : !!
     634              : !! INPUTS
     635              : !!
     636              : !! OUTPUT
     637              : !!
     638              : !! SOURCE
     639              : 
     640          486 : subroutine anaddb_driver_interatomic_force_constants(driver, ifc, dtset, crystal, ddb, ana_ncid, comm)
     641              : 
     642              : !Arguments -------------------------------
     643              :  class(anaddb_driver_type), intent(inout):: driver
     644              :  type(ifc_type), intent(out):: ifc
     645              :  type(anaddb_dataset_type), intent(in):: dtset
     646              :  type(crystal_t), intent(in):: crystal
     647              :  type(ddb_type), intent(in):: ddb
     648              :  integer, intent(in):: ana_ncid
     649              :  integer, intent(in):: comm
     650              : 
     651              : !Local variables -------------------------------
     652              :  integer, parameter:: master = 0
     653              :  integer:: my_rank
     654              :  integer:: ii
     655          378 :  type(ifc_type):: Ifc_coarse
     656              :  character(len = 500):: msg
     657              :  integer:: ngqpt_coarse(3)
     658              :  integer:: units(2)
     659              : ! ************************************************************************
     660              : 
     661          162 :  units = [std_out, ab_out]
     662              : 
     663         4428 :   write(msg, '(a, a, (80a), a, a, a, a)' ) ch10, ('=',ii = 1, 80), ch10, ch10, &
     664         4482 :     ' Calculation of the interatomic forces ',ch10
     665           54 :   call wrtout(units, msg)
     666              : 
     667          213 :  if (any(dtset%qrefine(:) > 1)) then
     668              :    ! Gaal-Nagy's algorithm in PRB 73 014117 [[cite:GaalNagy2006]]
     669              :    ! Build the IFCs using the coarse q-mesh.
     670            4 :    do ii = 1, 3
     671            4 :      ngqpt_coarse(ii) = dtset%ngqpt(ii) / dtset%qrefine(ii)
     672              :    end do
     673              :    call Ifc_coarse%init(crystal, ddb, &
     674              :      dtset%brav, dtset%asr, dtset%symdynmat, dtset%dipdip, dtset%rfmeth, ngqpt_coarse, dtset%nqshft, dtset%q1shft, &
     675              :      driver%epsinf, driver%zeff, driver%qdrp_cart, &
     676              :      dtset%nsphere, dtset%rifcsph, dtset%prtsrlr, dtset%enunit, dtset%sys_dim, comm, &
     677            1 :      dipquad=dtset%dipquad, quadquad=dtset%quadquad, dielt_env=dtset%dielt_env,dielt_thick=dtset%dielt_thick)
     678              : 
     679              :    ! Now use the coarse q-mesh to fill the entries in dynmat(q)
     680              :    ! on the dense q-mesh that cannot be obtained from the DDB file.
     681              :    call ifc%init(crystal, ddb, &
     682              :     dtset%brav, dtset%asr, dtset%symdynmat, dtset%dipdip, dtset%rfmeth, &
     683              :     dtset%ngqpt(1:3), dtset%nqshft, dtset%q1shft, driver%epsinf, driver%zeff, driver%qdrp_cart, &
     684              :     dtset%nsphere, dtset%rifcsph, dtset%prtsrlr, dtset%enunit, dtset%sys_dim, comm, &
     685              :     Ifc_coarse=Ifc_coarse, dipquad=dtset%dipquad, quadquad=dtset%quadquad, &
     686            1 :     dielt_env=dtset%dielt_env, dielt_thick=dtset%dielt_thick)
     687            1 :    call Ifc_coarse%free()
     688              : 
     689              :  else
     690              :    call ifc%init(crystal, ddb, &
     691              :      dtset%brav, dtset%asr, dtset%symdynmat, dtset%dipdip, dtset%rfmeth, &
     692              :      dtset%ngqpt(1:3), dtset%nqshft, dtset%q1shft, driver%epsinf, driver%zeff, driver%qdrp_cart, &
     693              :      dtset%nsphere, dtset%rifcsph, dtset%prtsrlr, dtset%enunit, dtset%sys_dim, comm, &
     694           53 :      dipquad=dtset%dipquad, quadquad=dtset%quadquad, dielt_env=dtset%dielt_env, dielt_thick=dtset%dielt_thick)
     695              :  end if
     696              : 
     697          108 :  call ifc%print([std_out])
     698              : 
     699              :  ! If asr==6 (rotational invariance) we also need the estimation of the IFCs moments from real space.
     700           54 :  if (dtset%asr==6 .and. dtset%flexoflag==0) then
     701            0 :          write(msg, '(a, a)' )' Rotational invariance: will generate IFCs derivatives from IFCs moments',ch10
     702            0 :          call ifc%get_dcdq(crystal,driver%dcdq,driver%dcdqdq, comm)
     703              :          ! If phi1 is not available from DDB, compute rotational invariance based on dcdq
     704              :          ! For polar materials, we have to be extra cautious: indeed the typical electrostatics
     705              :          ! model used to remove the non-analytical part is not invariant under rotation !
     706              :          ! In 3D, the model leads to a divergent IFCs derivatives -> we cannot correct anything !
     707              :          ! In 2D, the model leads to a finite torque and IFCs derivatives. We can add them back
     708              :          ! during the imposition of rotational invariance...
     709              :  end if
     710              : 
     711              :  ! Compute speed of sound.
     712           54 :  if (dtset%vs_qrad_tolkms(1) > zero) then
     713            0 :    call ifc%speedofsound(crystal, dtset%vs_qrad_tolkms, ana_ncid, comm)
     714              :  end if
     715              : 
     716              :  ! Print analysis of the real-space interatomic force constants
     717              :  ! TODO: ifc_out should not have side effects
     718           54 :  my_rank = xmpi_comm_rank(comm)
     719           54 :  if (my_rank == master .and. dtset%ifcout /= 0) then
     720           13 :    call ifc%write(dtset%ifcana, dtset%atifcflg, dtset%ifcout, dtset%prt_ifc, ana_ncid, dtset%prefix_outdata)
     721              :  end if
     722              : 
     723           54 : end subroutine anaddb_driver_interatomic_force_constants
     724              : !!***
     725              : 
     726              : !!****f* m_anaddb_driver/anaddb_driver_phdos
     727              : !! NAME
     728              : !! anaddb_driver_phdos
     729              : !!
     730              : !! FUNCTION
     731              : !! Compute phonon density of states.
     732              : !!
     733              : !! INPUTS
     734              : !!
     735              : !! OUTPUT
     736              : !!
     737              : !! SOURCE
     738              : 
     739           11 : subroutine anaddb_driver_phdos(driver, dtset, crystal, ifc, comm)
     740              : 
     741              : !Arguments -------------------------------
     742              :  class(anaddb_driver_type), intent(inout):: driver
     743              :  type(anaddb_dataset_type), intent(in):: dtset
     744              :  type(crystal_t), intent(in):: crystal
     745              :  type(ifc_type), intent(in):: ifc
     746              :  integer, intent(in):: comm
     747              : 
     748              : !Local variables -------------------------------
     749              :  integer, parameter:: master = 0
     750              :  integer:: my_rank
     751              :  integer:: ii
     752              :  integer:: phdos_ncid, ncerr
     753              :  character(len = fnlen):: phibz_prefix
     754              :  character(len = 500):: msg
     755          143 :  type(phdos_t):: Phdos
     756              :  integer:: units(2)
     757              :  integer:: count_wminmax(2)
     758              :  real(dp):: wminmax(2)
     759              : ! ************************************************************************
     760              : 
     761              :  ABI_UNUSED(driver%natom)
     762           11 :  my_rank = xmpi_comm_rank(comm)
     763           33 :  units = [std_out, ab_out]
     764              : 
     765          891 :  write(msg, '(a, (80a), 4a)')ch10, ('=',ii = 1, 80), ch10, ch10, ' Calculation of phonon density of states ',ch10
     766           11 :  call wrtout(units, msg)
     767              : 
     768              :  ! Only 1 shift in q-mesh
     769           11 :  wminmax = zero
     770           11 :  phibz_prefix = trim(" ")
     771              :  !phibz_prefix = "freq_displ" ! Uncomment this line to activate output of PHIBZ
     772              :  !                              ^^^^  GA: What the hell? FIXME ^^^^^
     773            0 :  do
     774              :    call Phdos%init(crystal, Ifc, dtset%prtdos, dtset%dosdeltae, dtset%dossmear, dtset%ng2qpt, 1, dtset%q2shft, &
     775           11 :                    phibz_prefix, wminmax, count_wminmax, comm, dos_maxmode=dtset%dos_maxmode)
     776           33 :    if (all(count_wminmax == 0)) exit
     777            0 :    wminmax(1) = wminmax(1) - abs(wminmax(1)) * 0.05; wminmax(2) = wminmax(2) + abs(wminmax(2)) * 0.05
     778            0 :    call phdos%free()
     779            0 :    write(msg, "(a, 2f8.5)")"Initial frequency mesh not large enough. Recomputing PHDOS with wmin, wmax: ",wminmax
     780            0 :    call wrtout(std_out, msg)
     781              :  end do
     782              : 
     783           11 :  if (my_rank == master) then
     784           11 :    call phdos%print_msqd(dtset%prefix_outdata, dtset%ntemper, dtset%tempermin, dtset%temperinc)
     785           11 :    call phdos%print(strcat(dtset%prefix_outdata, "_PHDOS"))
     786           11 :    call phdos%print_debye(crystal%ucvol)
     787           11 :    call phdos%print_thermo(strcat(dtset%prefix_outdata, "_THERMO"), dtset%ntemper, dtset%tempermin, dtset%temperinc)
     788              : 
     789           11 :    ncerr = nctk_open_create(phdos_ncid, strcat(dtset%prefix_outdata, "_PHDOS.nc"), xmpi_comm_self)
     790           11 :    NCF_CHECK_MSG(ncerr, "Creating PHDOS.nc file")
     791           11 :    NCF_CHECK(crystal%ncwrite(phdos_ncid))
     792           11 :    call phdos%ncwrite(phdos_ncid)
     793           11 :    NCF_CHECK(nf90_close(phdos_ncid))
     794              :  end if
     795              : 
     796           11 :  call phdos%free()
     797              : 
     798           11 : end subroutine anaddb_driver_phdos
     799              : !!***
     800              : 
     801              : !!****f* m_anaddb_driver/anaddb_driver_thermal_supercell
     802              : !! NAME
     803              : !! anaddb_driver_thermal_supercell
     804              : !!
     805              : !! FUNCTION
     806              : !!
     807              : !! INPUTS
     808              : !!
     809              : !! OUTPUT
     810              : !!
     811              : !! SOURCE
     812              : 
     813            1 : subroutine anaddb_driver_thermal_supercell(driver, dtset, crystal, ifc)
     814              : 
     815              : !Arguments -------------------------------
     816              :  class(anaddb_driver_type), intent(in):: driver
     817              :  type(anaddb_dataset_type), intent(in):: dtset
     818              :  type(crystal_t), intent(in):: crystal
     819              :  type(ifc_type), intent(in):: ifc
     820              : 
     821              : !Local variables -------------------------------
     822            1 :  type(supercell_type), allocatable:: thm_scells(:)
     823              : ! ************************************************************************
     824              : 
     825              :  ABI_UNUSED(driver%natom)
     826           13 :  ABI_MALLOC(thm_scells, (dtset%ntemper))
     827            1 :  call zacharias_supercell_make(crystal, ifc, dtset%ntemper, dtset%thermal_supercell, dtset%tempermin, dtset%temperinc, thm_scells)
     828            1 :  call zacharias_supercell_print(dtset%prefix_outdata, dtset%ntemper, dtset%tempermin, dtset%temperinc, thm_scells)
     829            1 :  call thermal_supercell_free(dtset%ntemper, thm_scells)
     830           11 :  ABI_FREE(thm_scells)
     831              : 
     832            1 : end subroutine anaddb_driver_thermal_supercell
     833              : !!***
     834              : 
     835              : !!****f* m_anaddb_driver/anaddb_driver_harmonic_thermo
     836              : !! NAME
     837              : !! anaddb_driver_harmonic_thermo
     838              : !!
     839              : !! FUNCTION
     840              : !! Phonon density of states and thermodynamical properties calculation
     841              : !!
     842              : !! INPUTS
     843              : !!
     844              : !! OUTPUT
     845              : !!
     846              : !! SOURCE
     847              : 
     848            4 : subroutine anaddb_driver_harmonic_thermo(driver, dtset, crystal, ifc, comm)
     849              : 
     850              : !Arguments -------------------------------
     851              :  class(anaddb_driver_type), intent(in):: driver
     852              :  type(anaddb_dataset_type), intent(in):: dtset
     853              :  type(crystal_t), intent(in):: crystal
     854              :  type(ifc_type), intent(in):: ifc
     855              :  integer, intent(in):: comm
     856              : 
     857              : !Local variables -------------------------------
     858              :  integer:: ii
     859              :  character(len = 500):: msg
     860              :  integer:: units(2)
     861              : ! ************************************************************************
     862              : 
     863              :  ABI_UNUSED(driver%natom)
     864           12 :  units = [std_out, ab_out]
     865              : 
     866          328 :  write(msg, '(a, (80a), a, a, a, a, a, a, a, a)' ) ch10, ('=',ii = 1, 80), ch10, ch10, &
     867            4 :   ' Calculation of phonon density of states, ',ch10, &
     868            4 :   '    thermodynamical properties, ',ch10, &
     869          332 :   '    and Debye-Waller factors.',ch10
     870            4 :  call wrtout(units, msg)
     871              : 
     872            4 :  if (dtset%thmflag == 1) then
     873            4 :    call harmonic_thermo(Ifc, crystal, ifc%amu, dtset, ab_out, dtset%prefix_outdata, comm)
     874              : 
     875            0 :  else if (dtset%thmflag == 2) then
     876            0 :    write(msg, '(a, (80a), a, a, a, a)' ) ch10, ('=',ii = 1, 80), ch10, ch10, ' Entering thm9 routine with thmflag = 2 ',ch10
     877            0 :    call wrtout(units, msg)
     878            0 :    call harmonic_thermo(Ifc, crystal, ifc%amu, dtset, ab_out, dtset%prefix_outdata, comm, thmflag=dtset%thmflag)
     879              :  end if
     880              : 
     881            4 : end subroutine anaddb_driver_harmonic_thermo
     882              : !!***
     883              : 
     884              : !!****f* m_anaddb_driver/anaddb_driver_dielectric_q0
     885              : !! NAME
     886              : !! anaddb_driver_dielectric_q0
     887              : !!
     888              : !! FUNCTION
     889              : !! Compute dielectric tensor at Gamma and related properties:
     890              : !! mode effective charges, oscillator strength.
     891              : !!
     892              : !! INPUTS
     893              : !!
     894              : !! OUTPUT
     895              : !!
     896              : !! SOURCE
     897              : 
     898           27 : subroutine anaddb_driver_dielectric_q0(driver, dtset, crystal, ifc, ddb, asrq0, ana_ncid, comm)
     899              : 
     900              : !Arguments -------------------------------
     901              :  class(anaddb_driver_type), intent(inout):: driver
     902              :  type(anaddb_dataset_type), intent(in):: dtset
     903              :  type(crystal_t), intent(in):: crystal
     904              :  type(ifc_type), intent(in):: ifc
     905              :  type(ddb_type), intent(in):: ddb
     906              :  type(asrq0_t), intent(inout):: asrq0
     907              :  integer, intent(in):: ana_ncid
     908              :  integer, intent(in):: comm
     909              : 
     910              : !Local variables -------------------------------
     911              :  integer:: ii, iblok
     912              :  integer:: rfelfd(4), rfphon(4), rfstrs(4)
     913              :  integer:: units(2)
     914              :  real(dp) :: eta
     915              :  character(len = 500):: msg
     916              :  real(dp):: qphnrm(3), qphon(3, 3)
     917           27 :  real(dp), allocatable:: eigval(:,:)
     918           27 :  real(dp), allocatable:: eigvec(:,:,:,:,:)
     919           27 :  real(dp), allocatable:: lst(:)
     920              : ! ************************************************************************
     921              : 
     922           81 :  units = [std_out, ab_out]
     923              : 
     924           81 :  ABI_MALLOC(eigval, (3, driver%natom))
     925          135 :  ABI_MALLOC(eigvec, (2, 3, driver%natom, 3, driver%natom))
     926           81 :  ABI_MALLOC(lst, (dtset%nph2l+1))
     927              : 
     928           91 :  lst = zero
     929              : 
     930              :  !***************************************************************
     931              :  ! Generates the dynamical matrix at Gamma
     932          108 :  qphon(:,1)=zero; qphnrm(1)=zero
     933              :  ! Generation of the dynamical matrix in cartesian coordinates
     934           27 :  if (dtset%ifcflag == 1) then
     935              :    ! Get d2cart using the interatomic forces and the
     936              :    ! long-range coulomb interaction through Ewald summation
     937              :    call gtdyn9(Ifc%acell, Ifc%atmfrc, driver%epsinf, Ifc%dipdip, &
     938              :      Ifc%dyewq0, driver%d2cart, crystal%gmet, Ifc%gprim, dtset%mpert, crystal%natom, &
     939              :      Ifc%nrpt, qphnrm(1), qphon, crystal%rmet, Ifc%rprim, Ifc%rpt, &
     940              :      Ifc%trans, crystal%ucvol, Ifc%wghatm, crystal%xred, driver%zeff, driver%qdrp_cart, &
     941              :      Ifc%ewald_option, eta, xmpi_comm_self, dtset%sys_dim,&
     942              :      dipquad=Ifc%dipquad, quadquad=Ifc%quadquad, dielt_thick=dtset%dielt_thick,&
     943           15 :                  dielt_env=dtset%dielt_env)
     944              : 
     945           12 :  else if (dtset%ifcflag == 0) then
     946              :    ! Look for the information in the DDB
     947          108 :    rfphon(1:2)=1; rfelfd(1:2)=2; rfstrs(1:2)=0
     948           12 :    call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, dtset%rfmeth)
     949           12 :    if (iblok == 0) then
     950         3268 :      driver%d2cart(:,1:dtset%msize)=zero
     951              :      ! GA: I notice this situation happen in test tutorespfn[telast_3]
     952              :      !     and I dont understand why the block is not found.
     953              :    else
     954              :      ! Copy the dynamical matrix in d2cart
     955       898112 :      driver%d2cart(:,1:dtset%msize)=ddb%val(:,:,iblok)
     956              :      ! Eventually impose the acoustic sum rule
     957           11 :      call asrq0%apply(crystal%natom, dtset%mpert, dtset%msize, qphon, Crystal, driver%d2cart)
     958              :    end if
     959              : 
     960              :  end if  ! end of the generation of the dynamical matrix at gamma.
     961              :  !***************************************************************
     962              : 
     963              :  ! Calculation of the eigenvectors and eigenvalues of the dynamical matrix
     964              :  call dfpt_phfrq(ddb%amu, driver%displ, driver%d2cart, eigval, eigvec, crystal%indsym, &
     965              :    dtset%mpert, crystal%nsym, crystal%natom, crystal%nsym, crystal%ntypat, driver%phfrq, qphnrm(1), qphon, &
     966           27 :    crystal%rprimd, dtset%symdynmat, crystal%symrel, crystal%symafm, crystal%typat, crystal%ucvol)
     967              : 
     968              :  ! calculation of the oscillator strengths, mode effective charge and
     969              :  ! dielectric tensor, frequency dependent dielectric tensor (dieflag)
     970              :  ! and mode by mode decomposition of epsilon if dieflag == 3
     971           27 :  if (dtset%dieflag /= 0) then
     972           17 :    if (driver%epsinf(1, 1)==one .and. driver%epsinf(2, 2)==one .and. driver%epsinf(3, 3)==one) then
     973            0 :      write(msg, '(7a)') ch10, &
     974            0 :       ' The DDB file does not contain the derivatives w.r.t. electric field perturbation. ',ch10, &
     975            0 :       ' This is mandatory to calculate the dielectric constant, ',ch10, &
     976            0 :       ' Please check your DDB file or use dieflag = 0.',ch10
     977            0 :      ABI_ERROR(msg)
     978              :    end if
     979              : 
     980         1377 :    write(msg, '(a, (80a), a)' ) ch10, ('=',ii = 1, 80), ch10
     981           17 :    call wrtout(units, msg)
     982              : 
     983              :    ! Print the electronic contribution to the dielectric tensor
     984              :    ! It can be extracted directly from the DDB if perturbation with E-field is present
     985              :    call ddb_diel(crystal, ddb%amu, dtset, driver%dielt_rlx, driver%displ, driver%d2cart, driver%epsinf, driver%fact_oscstr, &
     986           17 :      ab_out, lst, dtset%mpert, crystal%natom, 0, driver%phfrq, comm, ana_ncid)
     987              :  end if
     988              : 
     989           27 :  ABI_SFREE(eigval)
     990           27 :  ABI_SFREE(eigvec)
     991           27 :  ABI_SFREE(lst)
     992              : 
     993           27 : end subroutine anaddb_driver_dielectric_q0
     994              : !!***
     995              : 
     996              : !!****f* m_anaddb_driver/anaddb_driver_nonlinear_response
     997              : !! NAME
     998              : !! anaddb_driver_nonlinear_response
     999              : !!
    1000              : !! FUNCTION
    1001              : !! Non-linear response: electrooptic and Raman (q = Gamma, TO modes only)
    1002              : !!
    1003              : !! INPUTS
    1004              : !!
    1005              : !! OUTPUT
    1006              : !!
    1007              : !! SOURCE
    1008              : 
    1009            2 : subroutine anaddb_driver_nonlinear_response(driver, dtset, crystal, ana_ncid, comm)
    1010              : 
    1011              : !Arguments -------------------------------
    1012              :  class(anaddb_driver_type), intent(inout):: driver
    1013              :  type(anaddb_dataset_type), intent(in):: dtset
    1014              :  type(crystal_t), intent(in):: crystal
    1015              :  integer, intent(in):: ana_ncid
    1016              :  integer, intent(in):: comm
    1017              : 
    1018              : !Local variables -------------------------------
    1019              :  integer, parameter:: master = 0
    1020              :  integer:: my_rank
    1021              :  real(dp):: qphnrm(3), qphon(3, 3)
    1022            2 :  real(dp), allocatable:: rsus(:,:,:)
    1023              : ! ************************************************************************
    1024              : 
    1025            2 :  my_rank = xmpi_comm_rank(comm)
    1026              : 
    1027           10 :  ABI_MALLOC(rsus, (3*driver%natom, 3, 3))
    1028              : 
    1029              :  ! Raman susceptibilities for the 1st list (only TO  modes at q = Gamma)
    1030            8 :  qphon(:,1)=zero
    1031            2 :  qphnrm(1)=zero
    1032            2 :  call ramansus(driver%d2cart, driver%dchide, driver%dchidt, driver%displ, dtset%mpert, crystal%natom, driver%phfrq, qphon, qphnrm(1), rsus, crystal%ucvol)
    1033              : 
    1034            2 :  if (my_rank == master) then
    1035            2 :    call defwrite_raman_terms(ana_ncid, crystal%natom, rsus, driver%phfrq)
    1036              :  end if
    1037              : 
    1038              :  ! EO coef:
    1039            2 :  call electrooptic(driver%dchide, dtset%dieflag, driver%epsinf, driver%fact_oscstr, crystal%natom, driver%phfrq, dtset%prtmbm, rsus, crystal%ucvol)
    1040              : 
    1041            2 :  ABI_SFREE(rsus)
    1042              : 
    1043            2 : end subroutine anaddb_driver_nonlinear_response
    1044              : !!***
    1045              : 
    1046              : !!****f* m_anaddb_driver/anaddb_driver_dielectric_nonana
    1047              : !! NAME
    1048              : !! anaddb_driver_dielectric_nonana
    1049              : !!
    1050              : !! FUNCTION
    1051              : !! Compute non-analyticity in the dielectric matrix and raman susceptibility
    1052              : !!
    1053              : !! INPUTS
    1054              : !!
    1055              : !! OUTPUT
    1056              : !!
    1057              : !! SOURCE
    1058              : 
    1059           24 : subroutine anaddb_driver_dielectric_nonana(driver, dtset, crystal, ddb, ana_ncid, comm)
    1060              : 
    1061              : !Arguments -------------------------------
    1062              : class(anaddb_driver_type), intent(inout):: driver
    1063              :  type(anaddb_dataset_type), intent(in):: dtset
    1064              :  type(crystal_t), intent(in):: crystal
    1065              :  type(ddb_type), intent(in):: ddb
    1066              :  integer, intent(in):: ana_ncid
    1067              :  integer, intent(in):: comm
    1068              : 
    1069              : !Local variables -------------------------------
    1070              :  integer, parameter:: master = 0
    1071              :  integer:: ii, iphl2
    1072              :  integer:: natom, nph2l
    1073              :  integer:: my_rank
    1074              :  integer:: units(2)
    1075              :  character(len = 500):: msg
    1076              :  real(dp):: qphnrm(3), qphon(3, 3)
    1077           24 :  real(dp), allocatable:: eigval(:,:)
    1078           24 :  real(dp), allocatable:: eigvec(:,:,:,:,:)
    1079           24 :  real(dp), allocatable:: rsus(:,:,:)
    1080           24 :  real(dp), allocatable:: lst(:)
    1081              : ! ************************************************************************
    1082              : 
    1083           24 :  my_rank = xmpi_comm_rank(comm)
    1084           72 :  units = [std_out, ab_out]
    1085              : 
    1086           24 :  natom = dtset%natom
    1087           24 :  nph2l = dtset%nph2l
    1088           72 :  ABI_MALLOC(eigval, (3, natom))
    1089          120 :  ABI_MALLOC(eigvec, (2, 3, natom, 3, natom))
    1090          120 :  ABI_MALLOC(rsus, (3*natom, 3, 3))
    1091           72 :  ABI_MALLOC(lst, (nph2l+1))
    1092           85 :  lst = zero
    1093              : 
    1094         1944 :  write(msg, '(a, (80a), a, a, a, a)' ) ch10, ('=',ii = 1, 80), ch10, ch10, ' Treat the second list of vectors ',ch10
    1095           24 :  call wrtout(units, msg)
    1096              : 
    1097           24 :  if (my_rank == master) then
    1098           24 :    iphl2 = 0
    1099           24 :    call defwrite_nonana_terms(ana_ncid, iphl2, nph2l, dtset%qph2l, dtset%natom, driver%phfrq, driver%displ, "define")
    1100           24 :    if (dtset%nlflag == 1) then
    1101            2 :      call defwrite_nonana_raman_terms(ana_ncid, iphl2, nph2l, dtset%natom, rsus, "define")
    1102              :    end if
    1103              :  end if
    1104              : 
    1105              :  !Get the log of product of the square of the phonon frequencies without non-analyticities (q = 0)
    1106              :  !For the Lyddane-Sachs-Teller relation, it is stored in lst(nph2+1)
    1107           24 :  if (dtset%dieflag /= 2 .and. dtset%dieflag /= 0) then
    1108          108 :    do ii = 4, 3*crystal%natom
    1109          108 :      lst(nph2l+1)=lst(nph2l+1)+2*log(driver%phfrq(ii))
    1110              :    end do
    1111              :  end if
    1112              : 
    1113              :  ! Examine every wavevector of this list
    1114           61 :  do iphl2 = 1, nph2l
    1115              : 
    1116              :    ! Initialisation of the phonon wavevector
    1117          148 :    qphon(:,1)=dtset%qph2l(:,iphl2)
    1118           37 :    qphnrm(1)=dtset%qnrml2(iphl2)
    1119              : 
    1120              :    ! Calculation of the eigenvectors and eigenvalues of the dynamical matrix
    1121              :    ! for the second list of wv (can include non-analyticities if q /= 0)
    1122              :    call dfpt_phfrq(ddb%amu, driver%displ, driver%d2cart, eigval, eigvec, crystal%indsym, &
    1123              :      dtset%mpert, crystal%nsym, crystal%natom, crystal%nsym, crystal%ntypat, driver%phfrq, qphnrm(1), qphon, &
    1124           37 :      crystal%rprimd, dtset%symdynmat, crystal%symrel, crystal%symafm, crystal%typat, crystal%ucvol)
    1125              : 
    1126              :    ! Write the phonon frequencies for the second list of wv (can include non-analyticities if q /= 0)
    1127           37 :    call dfpt_prtph(driver%displ, dtset%eivec, dtset%enunit, ab_out, dtset%natom, driver%phfrq, qphnrm(1), qphon)
    1128              :    ! TODO: Mode effective charge could be printed here for LO modes (EB)
    1129              : 
    1130           37 :    if (my_rank == master) then
    1131              :      ! Loop is not MPI-parallelized--> no need for MPI-IO API.
    1132           37 :      call defwrite_nonana_terms(ana_ncid, iphl2, nph2l, dtset%qph2l, dtset%natom, driver%phfrq, driver%displ, "write")
    1133              :    end if
    1134              : 
    1135              :    ! Get the log of product of the square of the phonon frequencies with non-analyticities (q-->0)
    1136              :    ! for the Lyddane-Sachs-Teller relation
    1137              :    ! The fourth mode should have positive frequency otherwise there is an instability: LST relationship should not be evaluated
    1138              :    ! Isn't it tested somewhere else (i.e. stop of the code if there are imaginary freq.)? (EB)
    1139           37 :    if (dtset%dieflag /= 2 .and. dtset%dieflag /= 0) then
    1140          149 :      do ii = 4, 3*crystal%natom
    1141          149 :        lst(iphl2)=lst(iphl2)+2*log(driver%phfrq(ii))
    1142              :      end do
    1143              :    end if
    1144              : 
    1145              :    ! Write Raman susceptibilities for the 2nd list (can includes LO modes if q /= 0 0 0)
    1146           61 :    if (dtset%nlflag == 1) then
    1147            4 :      call ramansus(driver%d2cart, driver%dchide, driver%dchidt, driver%displ, dtset%mpert, crystal%natom, driver%phfrq, qphon, qphnrm(1), rsus, crystal%ucvol)
    1148            4 :      if (my_rank == master) then
    1149            4 :        call defwrite_nonana_raman_terms(ana_ncid, iphl2, nph2l, dtset%natom, rsus, "write")
    1150              :      end if
    1151              :    end if  ! nlflag = 1 (Raman suscep for the 2nd list of wv.)
    1152              :  end do  ! iphl2
    1153              : 
    1154              :  ! Lyddane-Sachs-Teller relation:
    1155           24 :  if (dtset%dieflag /= 2 .and. dtset%dieflag /= 0) then
    1156              :    call ddb_diel(crystal, ddb%amu, dtset, driver%dielt_rlx, driver%displ, driver%d2cart, driver%epsinf, driver%fact_oscstr, &
    1157            9 :      ab_out, lst, dtset%mpert, crystal%natom, nph2l, driver%phfrq, comm, ana_ncid)
    1158              :  end if
    1159              : 
    1160           24 :  ABI_SFREE(eigval)
    1161           24 :  ABI_SFREE(eigvec)
    1162           24 :  ABI_SFREE(rsus)
    1163           24 :  ABI_SFREE(lst)
    1164              : 
    1165           24 : end subroutine anaddb_driver_dielectric_nonana
    1166              : !!***
    1167              : 
    1168              : !!****f* m_anaddb_driver/anaddb_driver_internal_strain
    1169              : !! NAME
    1170              : !! anaddb_driver_internal_strain
    1171              : !!
    1172              : !! FUNCTION
    1173              : !!
    1174              : !! INPUTS
    1175              : !!
    1176              : !! OUTPUT
    1177              : !!
    1178              : !! SOURCE
    1179              : 
    1180            6 : subroutine anaddb_driver_internal_strain(driver, dtset, ddb, asrq0)
    1181              : 
    1182              : !Arguments -------------------------------
    1183              :  class(anaddb_driver_type), intent(inout):: driver
    1184              :  type(anaddb_dataset_type), intent(in):: dtset
    1185              :  type(ddb_type), intent(in):: ddb
    1186              :  type(asrq0_t), intent(in):: asrq0
    1187              : 
    1188              : !Local variables -------------------------------
    1189              :  integer:: ii, iblok
    1190              :  integer:: prt_internalstr
    1191              :  integer:: units(2)
    1192              :  integer:: rfelfd(4), rfphon(4), rfstrs(4)
    1193              :  character(len = 500):: msg
    1194              :  real(dp):: qphnrm(3), qphon(3, 3)
    1195              : ! ************************************************************************
    1196              : 
    1197           18 :  units = [std_out, ab_out]
    1198              : 
    1199              :  ! Here treating the internal strain tensors at Gamma point
    1200          492 :  write(msg, '(a, a, (80a), a, a, a, a)') ch10, ('=',ii = 1, 80), ch10, ch10, &
    1201          498 :   ' Calculation of the internal-strain  tensor',ch10
    1202            6 :  call wrtout(units, msg)
    1203              : 
    1204            6 :  if (dtset%instrflag == 1) then
    1205            6 :    call wrtout(std_out, 'instrflag = 1, so extract the internal strain constant from the 2DTE')
    1206              : 
    1207              :    ! looking after the no. of blok that contains the internal strain tensor
    1208           24 :    qphon(:,1)=zero; qphnrm(1)=zero
    1209           54 :    rfphon(1:2)=0; rfelfd(1:2)=0; rfstrs(1:2)=3
    1210              : 
    1211            6 :    call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, dtset%rfmeth)
    1212            6 :    if (iblok == 0) then
    1213            0 :      ABI_ERROR("DDB file must contain both uniaxial and shear strain for piezoelectric, Check your calculations")
    1214              :    end if
    1215              : 
    1216              :    ! then print the internal stain tensor
    1217            6 :    prt_internalstr = 2
    1218            6 :    call ddb_internalstr(dtset%asr, ddb%val, asrq0%d2asr, iblok, driver%instrain, ab_out, dtset%mpert, ddb%natom, ddb%nblok, prt_internalstr)
    1219              :  end if
    1220              : 
    1221            6 : end subroutine anaddb_driver_internal_strain
    1222              : !!***
    1223              : 
    1224              : !!****f* m_anaddb_driver/anaddb_driver_elastic_tensor
    1225              : !! NAME
    1226              : !! anaddb_driver_elastic_tensor
    1227              : !!
    1228              : !! FUNCTION
    1229              : !!
    1230              : !! INPUTS
    1231              : !!
    1232              : !! OUTPUT
    1233              : !!
    1234              : !! SOURCE
    1235              : 
    1236            6 : subroutine anaddb_driver_elastic_tensor(driver, dtset, crystal, ddb, asrq0, ana_ncid)
    1237              : 
    1238              : !Arguments -------------------------------
    1239              :  class(anaddb_driver_type), intent(inout):: driver
    1240              :  type(anaddb_dataset_type), intent(in):: dtset
    1241              :  type(crystal_t), intent(in):: crystal
    1242              :  type(ddb_type), intent(in):: ddb
    1243              :  type(asrq0_t), intent(inout):: asrq0
    1244              :  integer, intent(in):: ana_ncid
    1245              : 
    1246              : !Local variables -------------------------------
    1247              :  integer:: ii, iblok, iblok_stress
    1248              :  integer:: units(2)
    1249              :  character(len = 500):: msg
    1250              :  integer:: rfelfd(4), rfphon(4), rfstrs(4)
    1251              :  real(dp):: qphnrm(3), qphon(3, 3)
    1252              :  real(dp):: compl(6, 6), compl_clamped(6, 6), compl_stress(6, 6)
    1253              :  real(dp):: elast_clamped(6, 6), elast_stress(6, 6)
    1254              : ! ************************************************************************
    1255              : 
    1256           18 :  units = [std_out, ab_out]
    1257              : 
    1258              :  ! here treating the elastic tensors at Gamma Point
    1259          492 :  write(msg, '(a, a, (80a), a, a, a, a, a, a)') ch10, ('=',ii = 1, 80), ch10, ch10, &
    1260          498 :   ' Calculation of the elastic and compliances tensor (Voigt notation)',ch10
    1261            6 :  call wrtout(units, msg)
    1262              : 
    1263            6 :  call wrtout(std_out, 'so extract the elastic constant from the 2DTE')
    1264              : 
    1265              :  ! look after the blok no. that contains the stress tensor
    1266           24 :  qphon(:,1)=zero; qphnrm(1)=zero
    1267           54 :  rfphon(1:2)=0; rfelfd(1:2)=0; rfstrs(1:2)=0
    1268              : 
    1269            6 :  call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, BLKTYP_d1E_xx)
    1270            6 :  iblok_stress = iblok
    1271              : 
    1272              :  ! look after the blok no.iblok that contains the elastic tensor
    1273           24 :  qphon(:,1)=zero; qphnrm(1)=zero
    1274           54 :  rfphon(1:2)=0; rfelfd(1:2)=0; rfstrs(1:2)=3
    1275              : 
    1276              :  ! for both diagonal and shear parts
    1277            6 :  call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, dtset%rfmeth)
    1278            6 :  if (iblok == 0) then
    1279            0 :    ABI_ERROR("DDB file must contain both uniaxial and shear strain when elaflag != 0, Check your calculations")
    1280              :  end if
    1281              : 
    1282              :  ! print the elastic tensor
    1283              :  call ddb_elast(dtset, crystal, ddb%val, compl, compl_clamped, compl_stress, asrq0%d2asr, &
    1284              :    driver%elast, elast_clamped, elast_stress, iblok, iblok_stress, &
    1285            6 :    driver%instrain, ab_out, dtset%mpert, crystal%natom, ddb%nblok, ana_ncid)
    1286              : 
    1287            6 : end subroutine anaddb_driver_elastic_tensor
    1288              : !!***
    1289              : 
    1290              : !!****f* m_anaddb_driver/anaddb_driver_piezoelectric_tensor
    1291              : !! NAME
    1292              : !! anaddb_driver_piezoelectric_tensor
    1293              : !!
    1294              : !! FUNCTION
    1295              : !!
    1296              : !! INPUTS
    1297              : !!
    1298              : !! OUTPUT
    1299              : !!
    1300              : !! SOURCE
    1301              : 
    1302            5 : subroutine anaddb_driver_piezoelectric_tensor(driver, dtset, crystal, ddb, ana_ncid)
    1303              : 
    1304              : !Arguments -------------------------------
    1305              :  class(anaddb_driver_type), intent(inout):: driver
    1306              :  type(anaddb_dataset_type), intent(in):: dtset
    1307              :  type(crystal_t), intent(in):: crystal
    1308              :  type(ddb_type), intent(in):: ddb
    1309              :  integer, intent(in):: ana_ncid
    1310              : 
    1311              : !Local variables -------------------------------
    1312              :  integer:: ii, iblok
    1313              :  integer:: units(2)
    1314              :  character(len = 500):: msg
    1315              :  integer:: rfelfd(4), rfphon(4), rfstrs(4)
    1316              :  real(dp):: qphnrm(3), qphon(3, 3)
    1317              :  real(dp):: piezo(6, 3)
    1318              : ! ************************************************************************
    1319              : 
    1320           15 :  units = [std_out, ab_out]
    1321              : 
    1322              :  ! Here treating the piezoelectric tensor at Gamma Point
    1323          410 :  write(msg, '(a, a, (80a), a, a, a, a, a)') ch10, ('=',ii = 1, 80), ch10, ch10, &
    1324            5 :  ' Calculation of the tensor related to piezoelectric effetc',ch10, &
    1325          415 :  '  (Elastic indices in Voigt notation)',ch10
    1326            5 :  call wrtout(units, msg)
    1327              : 
    1328            5 :  call wrtout(std_out, 'extract the piezoelectric constant from the 2DTE')
    1329              : 
    1330              :  ! Looking for the gamma point block
    1331           20 :  qphon(:,1)=zero; qphnrm(1)=zero
    1332           45 :  rfphon(1:2)=0; rfelfd(1:2)=0; rfstrs(1:2)=3
    1333              : 
    1334              :  ! For both diagonal and shear parts
    1335            5 :  call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, dtset%rfmeth)
    1336            5 :  if (iblok == 0) then
    1337            0 :    ABI_ERROR("DDB file must contain both uniaxial and shear strain for piezoelectric, Check your calculations")
    1338              :  end if
    1339              : 
    1340              :  ! Then print out the piezoelectric constants
    1341              :  call ddb_piezo(dtset, ddb%val, driver%dielt_rlx, driver%elast, iblok, &
    1342              :      & driver%instrain, ab_out, dtset%mpert, crystal%natom, ddb%nblok, piezo, &
    1343            5 :      & crystal%ucvol, ana_ncid)
    1344              : 
    1345            5 : end subroutine anaddb_driver_piezoelectric_tensor
    1346              : !!***
    1347              : 
    1348              : !!****f* m_anaddb_driver/anaddb_driver_flexoelectric_tensor
    1349              : !! NAME
    1350              : !! anaddb_driver_flexoelectric_tensor
    1351              : !!
    1352              : !! FUNCTION
    1353              : !!
    1354              : !! INPUTS
    1355              : !!
    1356              : !! OUTPUT
    1357              : !!
    1358              : !! SOURCE
    1359              : 
    1360            2 : subroutine anaddb_driver_flexoelectric_tensor(driver, dtset, crystal, ddb, ddb_lw, ddb_hdr, asrq0)
    1361              : 
    1362              : !Arguments -------------------------------
    1363              :  class(anaddb_driver_type), intent(in):: driver
    1364              :  type(anaddb_dataset_type), intent(in):: dtset
    1365              :  type(crystal_t), intent(in):: crystal
    1366              :  type(ddb_type), intent(in):: ddb, ddb_lw
    1367              :  type(ddb_hdr_type), intent(in):: ddb_hdr
    1368              :  type(asrq0_t), intent(in):: asrq0
    1369              : 
    1370              : !Local variables -------------------------------
    1371              :  integer:: ii
    1372              :  integer:: units(2)
    1373              :  character(len = 500):: msg
    1374              : ! ************************************************************************
    1375              : 
    1376            6 :  units = [std_out, ab_out]
    1377              : 
    1378              :  ! Here treating the flexoelectric tensor
    1379          164 :  write(msg, '(a, a, (80a), a, a, a, a)') ch10, ('=',ii = 1, 80), ch10, ch10, &
    1380          166 :  ' Calculation of the tensors related to flexoelectric effect',ch10
    1381            2 :  call wrtout(units, msg)
    1382              : 
    1383              :  ! Compute and print the contributions to the flexoelectric tensor
    1384              :  call ddb_flexo(dtset%asr, asrq0%d2asr, ddb, ddb_lw, ddb_hdr%ddb_version, crystal, &
    1385            2 :      & dtset%filename_ddb, dtset%flexoflag, dtset%prtvol, driver%zeff)
    1386              : 
    1387            2 : end subroutine anaddb_driver_flexoelectric_tensor
    1388              : 
    1389              : !!***
    1390              : 
    1391              : !!****f* m_anaddb_driver/anaddb_driver_get_dcdq
    1392              : !! NAME
    1393              : !! anaddb_driver_get_dcdq
    1394              : !!
    1395              : !! FUNCTION
    1396              : !!
    1397              : !! INPUTS
    1398              : !!
    1399              : !! OUTPUT
    1400              : !!
    1401              : !! SOURCE
    1402              : 
    1403            1 : subroutine anaddb_driver_get_dcdq(driver, dtset, ddb, ddb_lw, ddb_hdr)
    1404              : 
    1405              : !Arguments -------------------------------
    1406              : class(anaddb_driver_type), intent(inout):: driver
    1407              : type(anaddb_dataset_type), intent(in):: dtset
    1408              : type(ddb_type), intent(in):: ddb, ddb_lw
    1409              : type(ddb_hdr_type), intent(in):: ddb_hdr
    1410              : 
    1411              : !Local variables -------------------------------
    1412              : integer:: ii
    1413              : integer:: units(2)
    1414              : character(len = 500):: msg
    1415              : !real(dp):: dcdq(3,ddb%natom,3,ddb%natom,3)
    1416              : 
    1417              : ! ************************************************************************
    1418              : 
    1419            3 :  units = [std_out, ab_out]
    1420              : 
    1421              : ! Here treating the flexoelectric tensor
    1422           82 :  write(msg, '(a, a, (80a), a, a, a, a)') ch10, ('=',ii = 1, 80), ch10, ch10, &
    1423           83 :         ' Extraction from DDB of the IFCs derivatives',ch10
    1424            1 :  call wrtout(units, msg)
    1425              : 
    1426              : ! Compute and print the contributions to the flexoelectric tensor
    1427            1 :  call ddb_phi1(ddb,ddb_lw,ddb_hdr%ddb_version, dtset%filename_ddb, driver%dcdq, driver%dcdqdq,ddb%natom)
    1428              : 
    1429            1 : end subroutine anaddb_driver_get_dcdq
    1430              : 
    1431              : !!***
    1432              : 
    1433              : !!****f* m_anaddb_driver/anaddb_driver_lattice_wannier
    1434              : !! NAME
    1435              : !! anaddb_driver_lattice_wannier
    1436              : !!
    1437              : !! FUNCTION
    1438              : !! Lattice Wannier function calculation.
    1439              : !! Compute the Dynamical matrix for a dense Q-mesh
    1440              : !! Input the eigenvectors and eigenvalues to the Lattcie Wannier module
    1441              : !! Construct the Lattice Wannier functions
    1442              : !!
    1443              : !! INPUTS
    1444              : !!
    1445              : !! OUTPUT
    1446              : !!
    1447              : !! SOURCE
    1448              : 
    1449            3 : subroutine anaddb_driver_lattice_wannier(driver, dtset, crystal, ifc, comm)
    1450              : 
    1451              : !Arguments -------------------------------
    1452              :  class(anaddb_driver_type), intent(in):: driver
    1453              :  type(anaddb_dataset_type), intent(in):: dtset
    1454              :  type(crystal_t),intent(in):: crystal
    1455              :  type(ifc_type), intent(in):: ifc
    1456              :  integer,intent(in):: comm
    1457              : 
    1458              : !Local variables -------------------------------
    1459              :  integer:: ii
    1460              :  character(len = 500):: msg
    1461              :  integer:: units(2)
    1462              : ! ************************************************************************
    1463              : 
    1464            9 :  units = [std_out, ab_out]
    1465              :  ABI_UNUSED(driver%natom)
    1466              : 
    1467          243 :  write(msg, '(a, (80a), 4a)')ch10, ('=',ii = 1, 80), ch10, ch10, ' Calculation of lattice Wannier functions ',ch10
    1468            3 :  call wrtout(units, msg)
    1469            3 :  call run_lattice_wannier(ifc=ifc, crystal=crystal, dtset=dtset, prefix=dtset%prefix_outdata, comm=comm)
    1470          243 :  write(msg, '(a, (80a))')ch10, ('=',ii = 1, 80)
    1471            3 :  call wrtout(units, msg)
    1472              : 
    1473            3 : end subroutine anaddb_driver_lattice_wannier
    1474              : !!***
    1475              : 
    1476              : !!***
    1477              : 
    1478              : !!****f* m_anaddb_driver/anaddb_driver_convertdim_dielt
    1479              : !! NAME
    1480              : !! anaddb_driver_convertdim_dielt
    1481              : !!
    1482              : !! FUNCTION
    1483              : !! Supposing a reduced dimensionality of the problem, convert DDB dielectric tensor
    1484              : !! to the low-dimensionality dielectric tensor of the isolated material. Indeed,
    1485              : !! first-principles calculations requires vacuum buffer(s) to isolate the low-dimensional
    1486              : !! materials, that spuriously contributes to the dielectric response of the whole slab
    1487              : !!
    1488              : !! INPUTS
    1489              : !!
    1490              : !! OUTPUT
    1491              : !!
    1492              : !! SOURCE
    1493              : 
    1494            2 : subroutine anaddb_driver_convertdim_dielt(driver, rprimd, sys_dim, dielt_thick)
    1495              : 
    1496              : !Arguments -------------------------------
    1497              :  class(anaddb_driver_type), intent(inout):: driver
    1498              :  integer,intent(in):: sys_dim
    1499              :  real(dp) :: dielt_thick(2), rprimd(3,3)
    1500              : 
    1501              : !Local variables -------------------------------
    1502              :  integer:: idir, jdir, kdir, bool_isolated(3)
    1503              :  real(dp) :: thick, epsinf_conv(3,3), acell(3)
    1504              :  character(len = 500):: msg
    1505              : 
    1506              : ! ************************************************************************
    1507            2 :  epsinf_conv=zero
    1508            2 :  thick = dielt_thick(1)-dielt_thick(2)
    1509            2 :  bool_isolated(:) = 0
    1510              :  ! When periodic, additional variable spaces coming from dynamical matrices derivatives
    1511            2 :  if (sys_dim == 1) then ! 3D
    1512              :     bool_isolated = 0
    1513            2 :  elseif (sys_dim == 2) then ! 2D yz
    1514            0 :     bool_isolated(1) = 1
    1515            2 :  elseif (sys_dim == 3) then ! 2D xz
    1516            0 :     bool_isolated(2) = 1
    1517            2 :  elseif (sys_dim == 4) then ! 2D xy
    1518            2 :     bool_isolated(3) = 1
    1519              :  else
    1520              :     write(msg,'(3a,i0)') &
    1521            0 :    'For dipole-dipole in 2D, the argument sys_dim should',ch10,&
    1522            0 :    'be between 1 and 4. However, sys_dim = ',sys_dim
    1523            0 :    ABI_ERROR(msg)
    1524              :  end if
    1525            8 :  do idir = 1,3
    1526           26 :    do jdir =1,3
    1527           24 :      if (bool_isolated(idir)==1 .and. bool_isolated(jdir)==0 .and. driver%epsinf(idir,jdir)>tol2) then
    1528              :        write(msg,'(3a)')&
    1529            0 :        'Along a confined + periodic directions, the dielectric tensor should be 0.',ch10,&
    1530            0 :        'However, a component is found to be larger than 1e-6. Please check your DDB file'
    1531            0 :        ABI_ERROR(msg)
    1532              :      end if
    1533              :    end do
    1534              :  end do
    1535            8 :  do idir=1,3
    1536           26 :    acell(idir)= sqrt(dot_product(rprimd(idir,:),rprimd(idir,:)))
    1537              :  end do
    1538              :  write(msg,'(2a)') &
    1539            2 :  'Conversion of the dielectric tensor for 2D materials to account for vacuum',ch10
    1540            6 :  call wrtout([std_out, ab_out],msg)
    1541            8 :  do kdir=1,3
    1542            8 :    if (bool_isolated(kdir)==1) then
    1543            8 :      do idir=1,3
    1544           26 :        do jdir=1,3
    1545           24 :          if (bool_isolated(idir)==0 .and. bool_isolated(jdir)==0) then
    1546              :            ! Capacitors in parallel for periodic directions between 2D and vacuum
    1547            8 :            if (idir==jdir) then
    1548            4 :              epsinf_conv(idir,jdir)=one-acell(kdir)/dielt_thick(1)*(one-driver%epsinf(idir,jdir))
    1549              :            else
    1550            4 :              epsinf_conv(idir,jdir)=acell(kdir)/dielt_thick(1)*driver%epsinf(idir,jdir)
    1551              :            end if
    1552           10 :          elseif (bool_isolated(idir)==1 .and. bool_isolated(jdir)==1) then
    1553              :            ! Capacitors in series for confined direction between 2D and vacuum
    1554            2 :            epsinf_conv(idir,jdir)= one/(one-acell(kdir)/thick*(one-one/driver%epsinf(idir,jdir)))
    1555              :          end if
    1556              :        end do
    1557              :      end do
    1558              :    end if
    1559              :  end do
    1560              :  write(msg,'(a,es16.8,a,es16.8,a,es16.8,a,es16.8,a,es16.8,a,es16.8,a,es16.8,a,es16.8,a,es16.8,a)')&
    1561            2 :  'Converted dielectric tensor',epsinf_conv(1,1),' ',epsinf_conv(1,2), '  ', epsinf_conv(1,3),' '&
    1562            2 :                               ,epsinf_conv(2,1),' ',epsinf_conv(2,2), '  ', epsinf_conv(2,3),' '&
    1563            4 :                               ,epsinf_conv(3,1),' ',epsinf_conv(3,2), '  ', epsinf_conv(3,3), ch10
    1564            6 :  call wrtout([std_out, ab_out],msg)
    1565           26 :  driver%epsinf = epsinf_conv
    1566              : 
    1567            2 : end subroutine anaddb_driver_convertdim_dielt
    1568              : 
    1569            0 : end module m_anaddb_driver
    1570              : !!***
        

Generated by: LCOV version 2.3-1