LCOV - code coverage report
Current view: top level - src/80_rttddft - m_rttddft_tdef.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 87.9 % 58 51
Test Date: 2026-09-21 13:49:52 Functions: 60.0 % 5 3

            Line data    Source code
       1              : !!****m* ABINIT/m_rttddft_tdef
       2              : !! NAME
       3              : !!  m_rttddft_tdef
       4              : !!
       5              : !! FUNCTION
       6              : !!  Contains definition of the tdef type
       7              : !!  related to time-dependent electric field
       8              : !!
       9              : !! COPYRIGHT
      10              : !!  Copyright (C) 2021-2026 ABINIT group (FBrieuc)
      11              : !!  This file is distributed under the terms of the
      12              : !!  GNU General Public License, see ~abinit/COPYING
      13              : !!  or http://www.gnu.org/copyleft/gpl.txt .
      14              : !!
      15              : !! SOURCE
      16              : 
      17              : #if defined HAVE_CONFIG_H
      18              : #include "config.h"
      19              : #endif
      20              : 
      21              : #include "abi_common.h"
      22              : 
      23              : module m_rttddft_tdef
      24              : 
      25              :  use defs_basis
      26              :  use defs_abitypes,   only: MPI_type
      27              : 
      28              :  use m_dtset,         only: dataset_type
      29              :  use m_errors,        only: msg_hndl
      30              :  use m_initylmg,      only: initylmg
      31              :  use m_profiling_abi, only: abimem_record
      32              :  use m_xmpi,          only: xmpi_bcast
      33              : 
      34              :  implicit none
      35              : 
      36              :  private
      37              : !!***
      38              : 
      39              : !! NAME
      40              : !! tdef_type: Time Dependent Electric Field type
      41              : !! Object containing the TD Electric field
      42              : !! for RT-TDDFT runs
      43              : !!
      44              : !! SOURCE
      45              :  type,public :: tdef_type
      46              : 
      47              :    integer  :: ef_type       !type of TD electric feld (Dirac or sin^2 pulse)
      48              :    real(dp) :: efield(3)     !TD external elec. field perturbation
      49              :    real(dp) :: ef_ezero(3)   !E_0 = |E_0|*polarization
      50              :    real(dp) :: vecpot(3)     !total vector potential
      51              :    real(dp) :: vecpot_ext(3) !external vector potential
      52              :    real(dp) :: vecpot_ind(3,2) !induced vector potential at t and t-dt
      53              :    real(dp) :: vecpot_red(3) !total vector potential in reduced coord. (in reciprocal space)
      54              :    real(dp) :: ef_tzero      !time at which elec field is switched on
      55              :    real(dp) :: ef_omega      !angular freq. of TD elec field
      56              :    real(dp) :: ef_tau        !time width of the pulse
      57              :    real(dp) :: ef_sin_a      !useful constant for sin^2 pulse
      58              :    real(dp) :: ef_sin_b      !useful constant for sin^2 pulse
      59              :    real(dp), allocatable :: kpa(:,:) ! contains kpts + A
      60              :                                      ! (in reduced coordinates in reciprocal space)
      61              :    logical  :: induced_vecpot ! Add the vector potential induced by the current density
      62              :                               ! in the Hamiltonian
      63              : 
      64              :    contains
      65              : 
      66              :    procedure :: init => tdef_init
      67              :    procedure :: update => tdef_update
      68              :    procedure :: restart => tdef_restart
      69              : 
      70              :  end type tdef_type
      71              : !!***
      72              : 
      73              : contains
      74              : !!***
      75              : 
      76              : !!****f* m_rttddft/tdef_init
      77              : !!
      78              : !! NAME
      79              : !!  tdef_init
      80              : !!
      81              : !! FUNCTION
      82              : !!  Update value of electric field and vector potential at time t
      83              : !!
      84              : !! INPUTS
      85              : !!  [tdef = tdef structure to update]
      86              : !!  td_ef_type = type of electric field (Dirac or sin^2 pulse)
      87              : !!  td_ef_pol = polarization
      88              : !!  td_ef_ezero = Amplitude (E_0 = |E_0|*polarization)
      89              : !!  td_ef_tzero = time at which the pulse is switched on
      90              : !!  td_ef_lambda = wavelength (for sin^2 pulse)
      91              : !!  td_ef_tau = time width of the pulse (for finite-width delta kick or sin^2 pulse)
      92              : !!  time = propagation time
      93              : !!  nkpt = number of kpoints
      94              : !!  kpts = kpoints array
      95              : !!
      96              : !! OUTPUT
      97              : !!  [tdef = updated tdef structure]
      98              : !!
      99              : !! SOURCE
     100           50 : subroutine tdef_init(tdef,td_ef_type,td_ef_pol,td_ef_ezero,td_ef_tzero,td_ef_lambda,td_ef_tau,td_ef_induced_vecpot,nkpt,kpts)
     101              : 
     102              :  !Arguments ------------------------------------
     103              :  !scalars
     104              :  class(tdef_type), intent(inout) :: tdef
     105              :  integer,          intent(in)    :: td_ef_type, td_ef_induced_vecpot, nkpt
     106              :  real(dp),         intent(in)    :: td_ef_ezero, td_ef_tzero, td_ef_lambda, td_ef_tau
     107              :  !arrays
     108              :  real(dp),         intent(in)    :: kpts(:,:)
     109              : 
     110              :  !Local variables-------------------------------
     111              :  real(dp),         intent(in)    :: td_ef_pol(3)
     112              : 
     113              : ! ***********************************************************************
     114              : 
     115           50 :  if (td_ef_type > 1 .or. td_ef_type < 0) then
     116            0 :    ABI_ERROR("Wrong value of td_ef_type")
     117              :  end if
     118              : 
     119           50 :  tdef%ef_type  = td_ef_type
     120          200 :  tdef%ef_ezero = td_ef_pol*td_ef_ezero
     121           50 :  tdef%ef_tau   = td_ef_tau
     122           50 :  tdef%ef_omega = 2.0_dp*pi*Speed_Light/td_ef_lambda !2*pi*f=2*pi*c/lambda
     123           50 :  tdef%ef_tzero = td_ef_tzero
     124           50 :  tdef%ef_sin_a = 2.0_dp*pi/td_ef_tau + tdef%ef_omega
     125           50 :  tdef%ef_sin_b = 2.0_dp*pi/td_ef_tau - tdef%ef_omega
     126           50 :  if (td_ef_induced_vecpot == 0) then
     127           48 :    tdef%induced_vecpot = .false.
     128            2 :  else if (td_ef_induced_vecpot == 1) then
     129            2 :    tdef%induced_vecpot = .true.
     130              :  else
     131            0 :     ABI_ERROR("Wrong value of td_ef_induced_vecpot")
     132              :  end if
     133              : 
     134          200 :  tdef%efield = zero
     135          200 :  tdef%vecpot = zero
     136          200 :  tdef%vecpot_ext = zero
     137          450 :  tdef%vecpot_ind = zero
     138          200 :  tdef%vecpot_red = zero
     139              : 
     140          150 :  ABI_MALLOC(tdef%kpa,(3,nkpt))
     141         3732 :  tdef%kpa = kpts
     142              : 
     143           50 : end subroutine tdef_init
     144              : !!***
     145              : 
     146              : !!****f* m_rttddft/tdef_update
     147              : !!
     148              : !! NAME
     149              : !!  tdef_update
     150              : !!
     151              : !! FUNCTION
     152              : !!  Update value of electric field and vector potential at time t
     153              : !!
     154              : !! INPUTS
     155              : !!  [tdef = tdef structure to update]
     156              : !!  dtset = dataset structure
     157              : !!  mpi_enreg = MPI communicators structure
     158              : !!  time = propagation time
     159              : !!  rprimd = cell vectors (direct space)
     160              : !!  gprimd = cell vectors (reciprocal space)
     161              : !!  kg = kpoints in reciprocal space
     162              : !!  mpsang = 1+maximum angular momentum for nonlocal pseudopotential (required by initylmg)
     163              : !!  npwarr = array holding npw for each k point
     164              : !!  ylm = real spherical harmonics for each G and k point
     165              : !!  ylmgr = gradient of real spherical harmonics for each G and k point
     166              : !!  current = total current density
     167              : !!
     168              : !! OUTPUT
     169              : !!  [tdef = updated tdef structure]
     170              : !!
     171              : !! SOURCE
     172         1795 : subroutine tdef_update(tdef,dtset,mpi_enreg,time,rprimd,gprimd,kg,mpsang,npwarr,ylm,ylmgr,current,update_vecpot_ind)
     173              : 
     174              :  !Arguments ------------------------------------
     175              :  !scalars
     176              :  class(tdef_type),   intent(inout) :: tdef
     177              :  type(dataset_type), intent(inout) :: dtset
     178              :  type(MPI_type),     intent(inout) :: mpi_enreg
     179              :  real(dp),           intent(in)    :: time
     180              :  real(dp),           intent(in)    :: rprimd(3,3)
     181              :  real(dp),           intent(in)    :: gprimd(3,3)
     182              :  integer,            intent(in)    :: kg(:,:)
     183              :  integer,            intent(in)    :: mpsang
     184              :  integer,            intent(in)    :: npwarr(:)
     185              :  real(dp),           intent(in)    :: current(:,:)
     186              :  real(dp),           intent(out)   :: ylm(:,:)
     187              :  real(dp),           intent(out)   :: ylmgr(:,:,:)
     188              :  logical, optional,  intent(in)    :: update_vecpot_ind
     189              : 
     190              :  !Local variables-------------------------------
     191              :  character(len=500) :: msg
     192              :  integer            :: i
     193              :  logical            :: lvecpot_ind
     194              :  real(dp)           :: tmp(3), expt
     195              : 
     196              : ! ***********************************************************************
     197              : 
     198              :  ! Update potential vector if time-dependent electric field perturbation is present
     199         2916 :  select case (tdef%ef_type)
     200              :    !No external field
     201              :    case (0)
     202              :    !Dirac pulse: vector potential is just an Heaviside function
     203              :    case (1)
     204         1121 :       if (abs(time-tdef%ef_tzero)<tol16) then
     205           44 :          tdef%efield(:) = tdef%ef_ezero(:)
     206              :       else
     207         4440 :          tdef%efield(:) = zero
     208              :       end if
     209         1121 :       if (time >= tdef%ef_tzero) then
     210         4324 :          tdef%vecpot_ext(:) = -tdef%ef_ezero(:)
     211              :       end if
     212              :    !"Finite" delta-kick pulse: Vector potential is a finite width sigmoid function
     213              :    case (2)
     214            0 :       expt = exp(-(time-tdef%ef_tzero)/tdef%ef_tau)
     215            0 :       tdef%efield(:) = tdef%ef_ezero(:)/tdef%ef_tau * expt/(1+expt)**2
     216            0 :       tdef%vecpot_ext(:) = -tdef%ef_ezero(:)/(1+expt)**2
     217              :    !Pulse with sin^2 shape:
     218              :    !E(t) = E0*cos(w*(t-t0))*sin^2(pi*(t-t0)/tau)
     219              :    !A(t) = -(E0/2w)*sin(w*(t-t0))+E0/(4*(2pi/tau+w))*sin((2pi/tau+w)*(t-t0))+E0/(4(2pi/tau-w))*sin((2pi/tau-w)*(t-t0))
     220              : !  case(2)
     221              : !     if (time >= tdef%ef_tzero+tdef%ef_tau) then
     222              : !        tdef%efield(:) = zero
     223              : !     else if (time >= tdef%ef_tzero) then
     224              : !        t = time-tdef%ef_tzero
     225              : !        tdef%efield(:) = tdef%ef_ezero*cos(tdef%ef_omega*t)*sin(pi*t/tdef%ef_tau)**2
     226              : !        tdef%vecpot_ext(:) = tdef%ef_ezero*(-sin(tdef%ef_omega*t)/(two*tdef%ef_omega) &
     227              : !                                          & +sin(tdef%ef_sin_a*t)/(four*tdef%ef_sin_a) &
     228              : !                                          & +sin(tdef%ef_sin_b*t)/(four*tdef%ef_sin_b))
     229              : !     end if
     230              :    case default
     231            0 :       write(msg,"(a)") "Unknown electric field type - check the value of td_ef_type"
     232         1795 :       ABI_ERROR(msg)
     233              :  end select
     234              : 
     235         1795 :  lvecpot_ind = .true.
     236         1795 :  if (present(update_vecpot_ind)) lvecpot_ind = update_vecpot_ind
     237              : 
     238              :  !Induced vector potential
     239              :  !Should deal with sppol?! How?
     240              :  !d^2A_ind/dt^2 = 4piJ(t)
     241              :  !A_ind(t+dt) = 2*A_ind(t) - A_ind(t-dt) + 4*pi*dt**2*J(t)
     242         1795 :  if (tdef%induced_vecpot) then
     243          102 :     if (lvecpot_ind) then
     244          404 :       tmp = tdef%vecpot_ind(:,2) ! t - 2dt
     245          404 :       tdef%vecpot_ind(:,2) = tdef%vecpot_ind(:,1) ! t - dt
     246          404 :       tdef%vecpot_ind(:,1) = 2*tdef%vecpot_ind(:,2) - tmp(:) + four*pi*(dtset%dtele**2)*current(:,1) ! t
     247              :     end if
     248          408 :     tdef%vecpot = tdef%vecpot_ext + tdef%vecpot_ind(:,1)
     249              :  else
     250         6772 :    tdef%vecpot = tdef%vecpot_ext
     251              :  end if
     252              : 
     253         7180 :  tdef%vecpot_red = matmul(transpose(rprimd),tdef%vecpot)
     254              : 
     255         1795 :  if (tdef%ef_type /= 0) then
     256              :    !Update the k+A grid used in cprojs
     257              :    !Divide by 2pi here seems necessary
     258         4484 :    do i = 1,3
     259       112100 :       tdef%kpa(i,:) = dtset%kptns(i,:) + tdef%vecpot_red(i)/(two*pi)
     260              :    end do
     261              :    ! update the spherical harmonics (computed at k+G+A)
     262              :    call initylmg(gprimd,kg,tdef%kpa,dtset%mkmem,mpi_enreg,mpsang,dtset%mpw,dtset%nband, &
     263         1121 :                & dtset%nkpt,npwarr,dtset%nsppol,0,rprimd,ylm,ylmgr)
     264              :  end if
     265              : 
     266         1795 : end subroutine tdef_update
     267              : !!***
     268              : 
     269              : !!****f* m_rttddft/tdef_restart
     270              : !!
     271              : !! NAME
     272              : !!  tdef_restart
     273              : !!
     274              : !! FUNCTION
     275              : !!  Update some values for restart of calculation with TD electric field
     276              : !!  Essentially needed if we account for induced vector potential
     277              : !!
     278              : !! INPUTS
     279              : !!  [tdef = tdef structure to update]
     280              : !!  mpi_enreg = MPI communicators structure
     281              : !!  restart_unit = unit of restart file to read
     282              : !!
     283              : !! OUTPUT
     284              : !!  [tdef = updated tdef structure]
     285              : !!
     286              : !! SOURCE
     287           20 : subroutine tdef_restart(tdef,mpi_enreg,restart_unit)
     288              : 
     289              :  !Arguments ------------------------------------
     290              :  !scalars
     291              :  class(tdef_type),   intent(inout) :: tdef
     292              :  type(MPI_type),     intent(inout) :: mpi_enreg
     293              :  integer,            intent(in)    :: restart_unit
     294              : 
     295              :  !Local variables-------------------------------
     296              :  integer :: ierr
     297              : 
     298              : ! ***********************************************************************
     299              : 
     300           20 :  if (tdef%induced_vecpot) then
     301            1 :       if (mpi_enreg%me == 0) then
     302            1 :          read(restart_unit,*) tdef%vecpot_ind(:,2)
     303            1 :          read(restart_unit,*) tdef%vecpot_ind(:,1)
     304              :       end if
     305              :  end if
     306              :  !Send to all procs
     307           20 :  call xmpi_bcast(tdef%vecpot_ind,0,mpi_enreg%comm_world,ierr)
     308              : 
     309           20 : end subroutine tdef_restart
     310              : !!***
     311              : 
     312            0 : end module m_rttddft_tdef
     313              : !!***
        

Generated by: LCOV version 2.3-1