LCOV - code coverage report
Current view: top level - src/80_rttddft - m_rttddft_propagators.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 93.5 % 184 172
Test Date: 2026-09-20 18:56:22 Functions: 100.0 % 2 2

            Line data    Source code
       1              : !!****m* ABINIT/m_rttddft_propagators
       2              : !! NAME
       3              : !!  m_rttddft_propagators
       4              : !!
       5              : !! FUNCTION
       6              : !!  Contains various propagators for the KS orbitals
       7              : !!
       8              : !! COPYRIGHT
       9              : !!  Copyright (C) 2021-2026 ABINIT group (FB)
      10              : !!  This file is distributed under the terms of the
      11              : !!  GNU General Public License, see ~abinit/COPYING
      12              : !!  or http://www.gnu.org/copyleft/gpl.txt .
      13              : !!
      14              : !! SOURCE
      15              : 
      16              : #if defined HAVE_CONFIG_H
      17              : #include "config.h"
      18              : #endif
      19              : 
      20              : #include "abi_common.h"
      21              : 
      22              : module m_rttddft_propagators
      23              : 
      24              :  use defs_basis
      25              :  use defs_abitypes,            only: MPI_type
      26              :  use defs_datatypes,           only: pseudopotential_type
      27              : 
      28              :  use m_bandfft_kpt,            only: bandfft_kpt, bandfft_kpt_type, &
      29              :                                    & bandfft_kpt_set_ikpt,          &
      30              :                                    & prep_bandfft_tabs
      31              :  use m_dtset,                  only: dataset_type
      32              :  use m_energies,               only: energies_type
      33              :  use m_errors,                 only: msg_hndl
      34              :  use m_gemm_nonlop_projectors, only: set_gemm_nonlop_ikpt
      35              :  use m_hamiltonian,            only: gs_hamiltonian_type, gspot_transgrid_and_pack
      36              :  use m_invovl,                 only: make_invovl
      37              :  use m_kg,                     only: mkkin, mkkpg
      38              :  use m_mkffnl,                 only: mkffnl
      39              :  use m_mpinfo,                 only: proc_distrb_cycle
      40              :  use m_profiling_abi,          only: abimem_record
      41              :  use m_rttddft,                only: rttddft_init_hamiltonian
      42              :  use m_rttddft_exponential,    only: rttddft_exp_taylor
      43              :  use m_rttddft_properties,     only: rttddft_calc_density, &
      44              :                                    & rttddft_calc_occ,     &
      45              :                                    & rttddft_calc_kin
      46              :  use m_rttddft_tdks,           only: tdks_type
      47              :  use m_specialmsg,             only: wrtout
      48              :  use m_xmpi,                   only: xmpi_comm_rank, xmpi_sum, xmpi_max
      49              : 
      50              :  implicit none
      51              : 
      52              :  private
      53              : !!***
      54              : 
      55              :  public :: rttddft_propagator_er
      56              :  public :: rttddft_propagator_emr
      57              : !!***
      58              : 
      59              : contains
      60              : !!***
      61              : 
      62              : !!****f* m_rttddft/rttddft_propagator_er
      63              : !!
      64              : !! NAME
      65              : !!  rttddft_propagator_er
      66              : !!
      67              : !! FUNCTION
      68              : !!  Main subroutine to propagate the KS orbitals using
      69              : !!  the Exponential Rule (ER) propagator.
      70              : !!
      71              : !! INPUTS
      72              : !!  dtset <type(dataset_type)> = all input variables for this dataset
      73              : !!  ham_k <type(gs_hamiltonian_type)> = Hamiltonian object
      74              : !!  istep <integer> = step number
      75              : !!  mpi_enreg <MPI_type> = MPI-parallelisation information
      76              : !!  psps <type(pseudopotential_type)>=variables related to pseudopotentials
      77              : !!  tdks <type(tdks_type)> = the tdks object to initialize
      78              : !!  calc_properties <logical> = logical governing the computation of
      79              : !!                              some properties (energies, occupations, eigenvalues..)
      80              : !!
      81              : !! NOTES
      82              : !!  Other propagators such as the Exponential Midpoint Rule (EMR)
      83              : !!  should usually be prefered over this one since the ER propagator
      84              : !!  alone violates time reversal symmetry. Using this propagator with
      85              : !!  the exponential approximated by Taylor expansion of order 1 leads
      86              : !!  to the famous Euler method which is fast and simple but unstable
      87              : !!  and thus insufficient for RT-TDDFT.
      88              : !!
      89              : !! SOURCE
      90         1755 : subroutine rttddft_propagator_er(dtset, istep, mpi_enreg, psps, tdks, calc_properties)
      91              : 
      92              :  !Arguments ------------------------------------
      93              :  !scalars
      94              :  integer,                    intent(in)    :: istep
      95              :  logical,          optional, intent(in)    :: calc_properties
      96              :  type(dataset_type),         intent(inout) :: dtset
      97              :  type(MPI_type),             intent(inout) :: mpi_enreg
      98              :  type(pseudopotential_type), intent(inout) :: psps
      99              :  type(tdks_type),    target, intent(inout) :: tdks
     100              : 
     101              :  !Local variables-------------------------------
     102              :  !scalars
     103              :  integer                        :: bdtot_index
     104              :  integer                        :: calc_forces
     105              :  integer                        :: dimffnl
     106              :  integer                        :: iband
     107              :  integer                        :: ibg, icg
     108              :  integer                        :: ider, idir
     109              :  integer                        :: ierr, ilm
     110              :  integer                        :: ikpt, ikpt_loc, ikg
     111              :  integer                        :: isppol
     112              :  integer                        :: istwf_k
     113              :  integer                        :: me_distrb
     114              :  integer                        :: me_bandfft
     115              :  integer                        :: my_ikpt, my_nspinor
     116              :  integer                        :: nband_k, nband_k_mem
     117              :  integer                        :: npw_k, nkpg
     118              :  integer                        :: shift
     119              :  integer                        :: spaceComm_distrb
     120              :  integer                        :: n4, n5, n6
     121              :  logical                        :: with_vxctau
     122              :  logical                        :: lcalc_properties
     123              :  type(energies_type)            :: energies
     124              :  type(bandfft_kpt_type),pointer :: my_bandfft_kpt => null()
     125         1755 :  type(gs_hamiltonian_type)      :: ham_k
     126              :  !arrays
     127         1755 :  integer,  allocatable          :: kg_k(:,:)
     128              :  real(dp), pointer              :: cg(:,:) => null()
     129              :  real(dp), pointer              :: cg0(:,:) => null()
     130         1755 :  real(dp), allocatable          :: enl(:)
     131              :  real(dp), pointer              :: eig(:) => null()
     132         1755 :  real(dp), allocatable          :: ffnl(:,:,:,:)
     133         1755 :  real(dp), allocatable          :: kpg_k(:,:)
     134              :  real(dp)                       :: kpoint(3)
     135              :  real(dp)                       :: kpa(3)
     136         1755 :  real(dp), allocatable          :: kinpw(:)
     137              :  real(dp), pointer              :: occ(:) => null()
     138              :  real(dp), pointer              :: occ0(:) => null()
     139         1755 :  real(dp), allocatable          :: ph3d(:,:,:)
     140         1755 :  real(dp), allocatable          :: vlocal(:,:,:,:)
     141         1755 :  real(dp), allocatable          :: vxctaulocal(:,:,:,:,:)
     142         1755 :  real(dp), allocatable          :: ylm_k(:,:)
     143              :  logical                        :: lproperties(4)
     144              : 
     145              : ! ***********************************************************************
     146              : 
     147              :  !Init MPI
     148         1755 :  spaceComm_distrb=mpi_enreg%comm_cell
     149          960 :  if (mpi_enreg%paral_kgb==1) spaceComm_distrb=mpi_enreg%comm_kpt
     150         1755 :  me_distrb=xmpi_comm_rank(spaceComm_distrb)
     151              : 
     152              :  !Do we calculate properties?
     153              :  !Governed by lproperties:
     154              :  !  lproperties(1) = compute energy contributions (kinetic)
     155              :  !  lproperties(2) = NL energy contribution in NC case
     156              :  !  lproperties(3) = eigenvalues
     157              :  !  lproperties(4) = occupations
     158         1755 :  lproperties(:) = .false.
     159         1755 :  lcalc_properties = .false.
     160         1755 :  if (present(calc_properties)) then
     161         1725 :    lcalc_properties = calc_properties
     162         1725 :    if (lcalc_properties) then
     163              :       !compute energy contributions
     164         1725 :       lproperties(1) = .true.
     165              :       !Init to zero different energies
     166         1725 :       call energies%init()
     167         1725 :       energies%entropy_ks=tdks%energies%entropy_ks
     168         1725 :       energies%e_corepsp=tdks%energies%e_corepsp
     169         1725 :       energies%e_ewald=tdks%energies%e_ewald
     170              :       !including NL part in NC case?
     171         1725 :       if (dtset%usepaw == 0) then
     172          200 :          lproperties(2) = .true.
     173          600 :          ABI_MALLOC(enl,(mpi_enreg%bandpp))
     174              :       else
     175         1525 :          ABI_MALLOC(enl,(0))
     176              :       end if
     177              :       !other properties
     178              :       ! eigenvalues
     179         1725 :       if (dtset%prteig /= 0 .or. dtset%prtdos /= 0) then
     180            0 :          if (mod(istep-1,dtset%td_prtstr) == 0) then
     181            0 :             lproperties(3) = .true.
     182            0 :             tdks%eigen(:) = zero
     183              :          end if
     184              :       end if
     185              :       ! occupations
     186         1725 :       lproperties(4) = .true.
     187       395485 :       tdks%occ(:) = zero
     188              :    end if
     189              :  end if
     190              : 
     191              :  !Set "vtrial" and initialize the Hamiltonian
     192         1755 :  call rttddft_init_hamiltonian(dtset,energies,ham_k,istep,mpi_enreg,psps,tdks)
     193              : 
     194         1755 :  my_nspinor=max(1,dtset%nspinor/mpi_enreg%nproc_spinor)
     195         1755 :  n4=dtset%ngfft(4); n5=dtset%ngfft(5); n6=dtset%ngfft(6)
     196        10530 :  ABI_MALLOC(vlocal,(n4,n5,n6,ham_k%nvloc))
     197         7020 :  with_vxctau=(size(tdks%vxctau)>0)
     198         1755 :  if(with_vxctau) then
     199            0 :    ABI_MALLOC(vxctaulocal,(n4,n5,n6,ham_k%nvloc,4))
     200              :  end if
     201         1755 :  if (dtset%ionmov/=0) then
     202              :    calc_forces=1
     203              :  else
     204         1755 :    calc_forces=0
     205              :  end if
     206              : 
     207              : !FB: @MT Needed?
     208              : !has_vectornd = (with_vectornd .EQ. 1)
     209              : !if(has_vectornd) then
     210              : !  ABI_MALLOC(vectornd_pac,(n4,n5,n6,ham_k%nvloc,3))
     211              : !  vectornd_pac=zero
     212              : !end if
     213              : 
     214         1755 :  icg=0; ibg=0
     215         1755 :  bdtot_index=0
     216              : 
     217              :  !*** LOOP OVER SPINS
     218         3510 :  do isppol=1,dtset%nsppol
     219              : 
     220         1755 :    ikpt_loc=0
     221         1755 :    ikg=0
     222              : 
     223              :    ! Set up local potential vlocal on the coarse FFT mesh from vtrial taking into account the spin.
     224              :    ! Also, continue to initialize the Hamiltonian.
     225              :    call gspot_transgrid_and_pack(isppol, psps%usepaw, dtset%paral_kgb, dtset%nfft, dtset%ngfft, tdks%nfftf, &
     226         1755 :                                & dtset%nspden, ham_k%nvloc, 1, tdks%pawfgr, mpi_enreg, tdks%vtrial, vlocal)
     227         1755 :    call ham_k%load_spin(isppol, vlocal=vlocal, with_nonlocal=.true.)
     228              : 
     229         1755 :    if (with_vxctau) then
     230              :       call gspot_transgrid_and_pack(isppol, psps%usepaw, dtset%paral_kgb, dtset%nfft, dtset%ngfft, tdks%nfftf, &
     231            0 :                                   & dtset%nspden, ham_k%nvloc, 4, tdks%pawfgr, mpi_enreg, tdks%vxctau, vxctaulocal)
     232            0 :       call ham_k%load_spin(isppol, vxctaulocal=vxctaulocal)
     233              :    end if
     234              : 
     235              : !FB: @MT Needed?
     236              : !  ! if vectornd is present, set it up for addition to ham_k similarly to how it's done for
     237              : !  ! vtrial. Note that it must be done for the three Cartesian directions. Also, the following
     238              : !  ! code assumes explicitly and implicitly that nvloc = 1. This should eventually be generalized.
     239              : !  if(has_vectornd) then
     240              : !     do idir = 1, 3
     241              : !        ABI_MALLOC(cgrvtrial,(dtset%nfft,dtset%nspden))
     242              : !        call transgrid(1,mpi_enreg,dtset%nspden,-1,0,0,dtset%paral_kgb,pawfgr,rhodum,rhodum,cgrvtrial,vectornd(:,idir))
     243              : !        call fftpac(isppol,mpi_enreg,dtset%nspden,n1,n2,n3,n4,n5,n6,dtset%ngfft,cgrvtrial,vectornd_pac(:,:,:,1,idir),2)
     244              : !        ABI_FREE(cgrvtrial)
     245              : !     end do
     246              : !     call ham_k%load_spin(isppol, vectornd=vectornd_pac)
     247              : !  end if
     248              : 
     249              :    !*** BIG FAT k POINT LOOP
     250         1755 :    ikpt = 0
     251        50570 :    do while (ikpt_loc < dtset%nkpt)
     252              : 
     253        47060 :       ikpt_loc = ikpt_loc + 1
     254        47060 :       ikpt = ikpt_loc
     255        47060 :       my_ikpt = mpi_enreg%my_kpttab(ikpt)
     256              : 
     257        47060 :       nband_k=dtset%nband(ikpt+(isppol-1)*dtset%nkpt)
     258        47060 :       if (mpi_enreg%paral_kgb==1) then
     259        26240 :          nband_k_mem=mpi_enreg%bandpp
     260              :       else
     261              :          nband_k_mem=nband_k
     262              :       end if
     263        47060 :       istwf_k=dtset%istwfk(ikpt)
     264        47060 :       npw_k=tdks%npwarr(ikpt)
     265              : 
     266        47060 :       if(proc_distrb_cycle(mpi_enreg%proc_distrb,ikpt,1,nband_k,isppol,me_distrb)) then
     267        19680 :          bdtot_index=bdtot_index+nband_k
     268        19680 :          cycle
     269              :       end if
     270              : 
     271        27380 :       if (mpi_enreg%paral_kgb==1) my_bandfft_kpt => bandfft_kpt(my_ikpt)
     272        27380 :       call bandfft_kpt_set_ikpt(ikpt,mpi_enreg)
     273              : 
     274        82140 :       ABI_MALLOC(kg_k,(3,npw_k))
     275       109520 :       ABI_MALLOC(ylm_k,(npw_k,psps%mpsang*psps%mpsang*psps%useylm))
     276     22474460 :       kg_k(:,1:npw_k)=tdks%kg(:,1+ikg:npw_k+ikg)
     277        27380 :       if (psps%useylm==1) then
     278       136300 :          do ilm=1,psps%mpsang*psps%mpsang
     279     21448840 :             ylm_k(1:npw_k,ilm)=tdks%ylm(1+ikg:npw_k+ikg,ilm)
     280              :          end do
     281              :       end if
     282              : 
     283              :       !** Set up the remaining k-dependent part of the Hamiltonian
     284       109520 :       kpoint(:)=dtset%kptns(:,ikpt) !k-point
     285       109520 :       kpa(:)=tdks%tdef%kpa(:,ikpt)  !k+A
     286              : 
     287              :       ! Kinetic energy
     288        82140 :       ABI_MALLOC(kinpw,(npw_k))
     289        27380 :       call mkkin(dtset%ecut,dtset%ecutsm,dtset%effmass_free,tdks%gmet,kg_k,kinpw,kpoint,npw_k,0,0,tdks%tdef%vecpot_red)
     290              : 
     291              :       ! Compute (k+G) vectors (only if useylm=1)
     292        27380 :       nkpg=3*calc_forces*dtset%nloalg(3)
     293       109520 :       ABI_MALLOC(kpg_k,(npw_k,nkpg))
     294              :       ! Compute nonlocal form factors ffnl at all (k+G):
     295        27380 :       ider=0;idir=0;dimffnl=1
     296       136900 :       ABI_MALLOC(ffnl,(npw_k,dimffnl,psps%lmnmax,psps%ntypat))
     297        27380 :       if (mpi_enreg%paral_kgb/=1 .or. istep<=tdks%first_step .or. tdks%tdef%ef_type/=0) then
     298        27236 :          if (nkpg > 0) call mkkpg(kg_k,kpg_k,kpa,nkpg,npw_k)
     299              :          call mkffnl(psps%dimekb,dimffnl,psps%ekb,ffnl,psps%ffspl,tdks%gmet,tdks%gprimd, &
     300              :                    & ider,idir,psps%indlmn,kg_k,kpg_k,kpa,psps%lmnmax,psps%lnmax,        &
     301              :                    & psps%mpsang,psps%mqgrid_ff,nkpg,npw_k,psps%ntypat,psps%pspso,       &
     302        27236 :                    & psps%qgrid_ff,tdks%rmet,psps%usepaw,psps%useylm,ylm_k,tdks%ylmgr)
     303              :       end if
     304              : 
     305              :       !** Load k-dependent part in the Hamiltonian datastructure
     306              :       !**  - Compute 3D phase factors
     307              :       !**  - Prepare various tabs in case of band-FFT parallelism
     308              :       !**  - Load k-dependent quantities in the Hamiltonian
     309       109520 :       ABI_MALLOC(ph3d,(2,npw_k,ham_k%matblk))
     310              :       call ham_k%load_k(kpt_k=kpa,istwf_k=istwf_k,npw_k=npw_k,kinpw_k=kinpw,kg_k=kg_k,kpg_k=kpg_k, &
     311        27380 :                       & ffnl_k=ffnl,ph3d_k=ph3d,compute_ph3d=.true.,compute_gbound=.true.)
     312              : 
     313              :       !** Load band-FFT tabs (transposed k-dependent arrays)
     314        27380 :       if (mpi_enreg%paral_kgb==1) then
     315         6560 :          if (istep<=tdks%first_step .or. tdks%tdef%ef_type/=0) then
     316         6416 :             call prep_bandfft_tabs(ham_k,ikpt,dtset%mkmem,mpi_enreg)
     317              :          end if
     318              :          call ham_k%load_k(npw_fft_k=my_bandfft_kpt%ndatarecv,    &
     319              :                          & gbound_k =my_bandfft_kpt%gbound,       &
     320              :                          & kinpw_k  =my_bandfft_kpt%kinpw_gather, &
     321              :                          & kg_k     =my_bandfft_kpt%kg_k_gather,  &
     322              :                          & kpg_k    =my_bandfft_kpt%kpg_k_gather, &
     323              :                          & ffnl_k   =my_bandfft_kpt%ffnl_gather,  &
     324         6560 :                          & ph3d_k   =my_bandfft_kpt%ph3d_gather)
     325              :       end if
     326              : 
     327              :       !** Build inverse of overlap matrix
     328        27380 :       if(psps%usepaw == 1 .and. (istep <= tdks%first_step .or. tdks%tdef%ef_type/=0)) then
     329        16164 :          call make_invovl(ham_k,dimffnl,ffnl,ph3d,mpi_enreg)
     330              :       end if
     331              : 
     332              :       ! Setup gemm_nonlop
     333        27380 :       if (tdks%gemm_nonlop_use_gemm) then
     334              :         call set_gemm_nonlop_ikpt(my_ikpt,ham_k%npw_fft_k,ham_k%istwf_k,ham_k%indlmn,&
     335            0 :         &    ham_k%ntypat,ham_k%nattyp,ham_k%gpu_option)
     336              :       end if
     337              : 
     338              :       !** Compute the exp[-i(S^{-1})H]*cg using Taylor expansion to approximate the exponential
     339        27380 :       cg => tdks%cg(:,icg+1:icg+nband_k*npw_k*my_nspinor)
     340              :       ! Compute properties "on-the-fly" if required
     341        27380 :       if (lcalc_properties) then
     342        27260 :          cg0 => tdks%cg0(:,icg+1:icg+nband_k*npw_k*my_nspinor)
     343        27260 :          occ => tdks%occ(bdtot_index+1:bdtot_index+nband_k)
     344        27260 :          occ0 => tdks%occ0(bdtot_index+1:bdtot_index+nband_k)
     345        27260 :          if (dtset%paral_kgb /= 1) then
     346              :             shift = bdtot_index
     347              :          else
     348         6560 :             me_bandfft = xmpi_comm_rank(mpi_enreg%comm_band)
     349         6560 :             shift = bdtot_index+me_bandfft*mpi_enreg%bandpp
     350              :          end if
     351              :          ! kinetic energy
     352        27260 :          if (lproperties(1)) then
     353              :             call rttddft_calc_kin(energies%e_kinetic,cg,dtset,ham_k,nband_k,npw_k,my_nspinor, &
     354        27260 :                                 & occ0,dtset%wtk(ikpt),mpi_enreg,my_bandfft_kpt)
     355              :          end if
     356              :          ! for eigenvalues
     357        27260 :          if (lproperties(3)) then
     358            0 :             eig => tdks%eigen(1+shift:nband_k_mem+shift)
     359              :          end if
     360              :          ! occupations
     361        27260 :          if (lproperties(4)) then
     362              :             !computed at istep-1 like energies and eigenvalues
     363              :             call rttddft_calc_occ(cg,cg0,dtset,ham_k,ikpt,ibg,isppol,mpi_enreg, &
     364        27260 :                                 & nband_k,npw_k,my_nspinor,occ,occ0,tdks)
     365              :          end if
     366              : 
     367              :          !Propagate cg and compute the requested properties
     368        27260 :          call rttddft_exp_taylor(cg,dtset,ham_k,mpi_enreg,nband_k,npw_k,my_nspinor,enl=enl,eig=eig)
     369              : 
     370              :          !Finish computing NL PSP part for NC PSP
     371        27260 :          if (lproperties(2)) then
     372         6080 :             do iband = 1, mpi_enreg%bandpp
     373         6080 :                energies%e_nlpsp_vfock=energies%e_nlpsp_vfock+dtset%wtk(ikpt)*tdks%occ0(shift+iband)*enl(iband)
     374              :             end do
     375              :          end if
     376              :       else
     377              :          !Propagate cg only
     378          120 :          call rttddft_exp_taylor(cg,dtset,ham_k,mpi_enreg,nband_k,npw_k,my_nspinor)
     379              :       end if
     380              : 
     381        27380 :       ABI_FREE(kg_k)
     382        27380 :       ABI_FREE(ylm_k)
     383        27380 :       ABI_FREE(kpg_k)
     384        27380 :       ABI_FREE(kinpw)
     385        27380 :       ABI_FREE(ffnl)
     386        27380 :       ABI_FREE(ph3d)
     387              : 
     388        27380 :       bdtot_index = bdtot_index+nband_k
     389              : 
     390              :       !** Also shift array memory if dtset%mkmem/=0
     391        29135 :       if (dtset%mkmem/=0) then
     392        27380 :          ibg=ibg+nband_k_mem
     393        27380 :          icg=icg+npw_k*my_nspinor*nband_k
     394        27380 :          ikg=ikg+npw_k
     395              :       end if
     396              : 
     397              :    end do !nkpt
     398              : 
     399              :  end do !nsppol
     400              : 
     401              :  ! Free memory
     402         1755 :  ABI_FREE(vlocal)
     403         1755 :  if(dtset%usekden/=0) then
     404            0 :    ABI_FREE(vxctaulocal)
     405              :  end if
     406         1755 :  call ham_k%free()
     407         1755 :  if (allocated(enl)) then
     408         1725 :    ABI_FREE(enl)
     409              :  end if
     410              : 
     411              :  !Keep the computed energies in memory
     412         1755 :  if (lcalc_properties) then
     413         1725 :    call xmpi_sum(energies%e_kinetic,mpi_enreg%comm_kptband,ierr)
     414         1725 :    call xmpi_sum(energies%e_nlpsp_vfock,mpi_enreg%comm_kptband,ierr)
     415         1725 :    call energies%copy(tdks%energies)
     416         1725 :    if (lproperties(3)) call xmpi_sum(tdks%eigen,mpi_enreg%comm_kptband,ierr)
     417         1725 :    if (lproperties(4)) call xmpi_sum(tdks%occ,mpi_enreg%comm_kpt,ierr)
     418              :  end if
     419              : 
     420         3510 : end subroutine rttddft_propagator_er
     421              : !!***
     422              : 
     423              : !!****f* m_rttddft/rttddft_propagator_emr
     424              : !!
     425              : !! NAME
     426              : !!  rttddft_propagator_emr
     427              : !!
     428              : !! FUNCTION
     429              : !!  Main subroutine to propagate the KS orbitals using
     430              : !!  the Exponential Midpoint Rule (EMR) propagator
     431              : !!
     432              : !! INPUTS
     433              : !!  dtset <type(dataset_type)>=all input variables for this dataset
     434              : !!  ham_k <type(gs_hamiltonian_type)> = Hamiltonian object
     435              : !!  istep <integer> = step number
     436              : !!  mpi_enreg <MPI_type> = MPI-parallelisation information
     437              : !!  psps <type(pseudopotential_type)>=variables related to pseudopotentials
     438              : !!  tdks <type(tdks_type)> = the tdks object to initialize
     439              : !!
     440              : !! OUTPUT
     441              : !!
     442              : !! NOTES
     443              : !!  This propagator is time reversible
     444              : !!  (if H(t+dt/2) and the exponential are computed exactly).
     445              : !!
     446              : !! SOURCE
     447           20 : subroutine rttddft_propagator_emr(dtset, istep, mpi_enreg, psps, tdks)
     448              : 
     449              :  !Arguments ------------------------------------
     450              :  !scalars
     451              :  integer,                    intent(in)    :: istep
     452              :  type(dataset_type),         intent(inout) :: dtset
     453              :  type(MPI_type),             intent(inout) :: mpi_enreg
     454              :  type(pseudopotential_type), intent(inout) :: psps
     455              :  type(tdks_type),            intent(inout) :: tdks
     456              : 
     457              :  !Local variables-------------------------------
     458              :  integer :: me
     459              :  !scalars
     460              :  character(len=500) :: msg
     461              :  integer            :: ics
     462              :  integer            :: ierr
     463              :  logical            :: lconv
     464              :  !arrays
     465           40 :  real(dp)           :: cg(SIZE(tdks%cg(:,1)),SIZE(tdks%cg(1,:)))
     466           40 :  real(dp)           :: diff(SIZE(tdks%cg(:,1)),SIZE(tdks%cg(1,:)))
     467              :  real(dp)           :: max_diff(2)
     468              : 
     469              : ! ***********************************************************************
     470              : 
     471      5276180 :  cg(:,:) = tdks%cg(:,:) !Psi(t)
     472              : 
     473              :  !** Predictor step
     474              :  ! predict psi(t+dt) using ER propagator
     475           20 :  call rttddft_propagator_er(dtset,istep,mpi_enreg,psps,tdks,calc_properties=.true.)
     476              :  ! for convergence check
     477      5276180 :  diff = tdks%cg
     478              :  ! estimate psi(t+dt/2) = (psi(t)+psi(t+dt))/2
     479      5276180 :  tdks%cg(:,:) = 0.5_dp*(tdks%cg(:,:)+cg(:,:))
     480              :  ! update electric field and vector potential to t+dt/2
     481              :  ! We decide here not to update the induced vector potential to t+dt/2 for simplicity
     482              :  call tdks%tdef%update(dtset,mpi_enreg,(istep-0.5_dp)*tdks%dt,tdks%rprimd,tdks%gprimd,tdks%kg, &
     483           20 :                      & psps%mpsang,tdks%npwarr,tdks%ylm,tdks%ylmgr,tdks%current,update_vecpot_ind=.false.)
     484              :  ! calc associated density at t+dt/2
     485           20 :  call rttddft_calc_density(dtset,mpi_enreg,psps,tdks)
     486              :  ! go back to time t ..
     487      5276180 :  tdks%cg(:,:) = cg(:,:)
     488              :  ! .. and evolve psi(t) using the EMR propagator with the estimated density at t+dt/2
     489           20 :  call rttddft_propagator_er(dtset,istep,mpi_enreg,psps,tdks)
     490              : 
     491              :  ! check convergence
     492      5276180 :  diff = abs(diff-tdks%cg)
     493           20 :  me = xmpi_comm_rank(mpi_enreg%comm_world)
     494      1758760 :  call xmpi_max(maxval(diff(1,:)),max_diff(1),mpi_enreg%comm_world,ierr)
     495      1758760 :  call xmpi_max(maxval(diff(2,:)),max_diff(2),mpi_enreg%comm_world,ierr)
     496           20 :  lconv = (max_diff(1) < dtset%td_scthr .and. max_diff(2) < dtset%td_scthr)
     497           20 :  ics = 0
     498           20 :  if (mpi_enreg%me == 0) then
     499           20 :    write(msg,'(a,a,i3,a,3(es8.2,1x),l1,a)') ch10, 'SC Step', ics, ' - ', max_diff(1), max_diff(2), &
     500           40 :                                           & dtset%td_scthr, lconv, ch10
     501           20 :    if (do_write_log) call wrtout(std_out,msg)
     502              :  end if
     503           20 :  if (.not. lconv) then
     504              :    !** Corrector steps
     505           10 :    do ics = 1, dtset%td_scnmax
     506              :       ! for convergence check
     507      1451530 :       diff = tdks%cg
     508              :       ! estimate psi(t+dt/2) = (psi(t)+psi(t+dt))/2
     509      1451530 :       tdks%cg(:,:) = 0.5_dp*(tdks%cg(:,:)+cg(:,:))
     510              :       ! calc associated density at t+dt/2
     511           10 :       call rttddft_calc_density(dtset,mpi_enreg,psps,tdks)
     512              :       ! Go back to time t ..
     513      1451530 :       tdks%cg(:,:) = cg(:,:)
     514              :       ! .. and evolve psi(t) using estimated density at t+dt/2
     515           10 :       call rttddft_propagator_er(dtset,istep,mpi_enreg,psps,tdks)
     516              :       ! check convergence
     517      1451530 :       diff = abs(diff-tdks%cg)
     518           10 :       me = xmpi_comm_rank(mpi_enreg%comm_world)
     519       483860 :       call xmpi_max(maxval(diff(1,:)),max_diff(1),mpi_enreg%comm_world,ierr)
     520       483860 :       call xmpi_max(maxval(diff(2,:)),max_diff(2),mpi_enreg%comm_world,ierr)
     521           10 :       lconv = (max_diff(1) < dtset%td_scthr .and. max_diff(2) < dtset%td_scthr)
     522           10 :       if (mpi_enreg%me == 0) then
     523           10 :          write(msg,'(a,a,i3,a,3(es8.2,1x),l1,a)') ch10, 'SC Step', ics, ' - ', max_diff(1), max_diff(2), &
     524           20 :                                                 & dtset%td_scthr, lconv, ch10
     525           10 :          if (do_write_log) call wrtout(std_out,msg)
     526              :       end if
     527           10 :       if (lconv) exit
     528              :    end do
     529              :  end if
     530              : 
     531           20 :  if (lconv) then
     532           20 :    write(msg,'(a,i4,a)') "Converged after ", ics, " self-consistent corrector steps"
     533           20 :    call wrtout(ab_out,msg)
     534           20 :    if (do_write_log) call wrtout(std_out,msg)
     535              :  else
     536            0 :    write(msg,'(a)') "Reached maximum number of corrector steps before convergence!"
     537            0 :    ABI_WARNING(msg)
     538            0 :    call wrtout(ab_out,msg)
     539              :  end if
     540              : 
     541           20 : end subroutine rttddft_propagator_emr
     542              : !!***
     543              : 
     544              : end module m_rttddft_propagators
     545              : !!***
        

Generated by: LCOV version 2.3-1