New real-time TDDFT implementation

There is an ongoing effort in refactoring the real-time TDDFT codes to comply with the new GPAW backend. There are two old rt-TDDFT implementations, one for LCAO mode and one for FD mode. This page documents the new gpaw.new.rttddft.RTTDDFT interface which is common for both modes. See Time-propagation TDDFT with LCAO and Time-propagation TDDFT for the old rt-TDDFT implementations.

Ported features

The following features from the old code have been ported

  • Reading and writing of restart files

  • Delta-kicks

  • The Explicit Crank-Nicolson and Semi-implicit Crank-Nicolson propagators

The following features are still to be ported

  • Logging

  • Parallel execution

  • Time-dependent potentials

  • The radiation-reaction potential

  • Linearization of the xc functional

  • Scaling factor for the dynamic part of the hamiltonian

User interface

The new interface can be used directly. The gpaw.new.rttddft.RTTDDFT can be initialized from

When starting from a DFT calculation or DFT file, the propagation algorithm can be specified using the td_algorithm keyword.

Example

First we do a standard ground-state calculation with the GPAW calculator in LCAO mode:

Some important points are:

  • In LCAO mode, the grid spacing is only used to calculate the Hamiltonian matrix and therefore a coarser grid than usual can be used.

  • Completely unoccupied bands should be left out of the calculation, since they are not needed.

  • The density convergence criterion should be a few orders of magnitude more accurate than in usual ground-state calculations.

  • One should use multipole-corrected Poisson solvers or other advanced Poisson solvers in any TDDFT run in order to guarantee the convergence of the potential with respect to the vacuum size. See the documentation on Advanced Poisson solvers.

  • Point group symmetries are disabled in TDDFT, since the symmetry is broken by the time-dependent potential. The TDDFT calculation will refuse to start if the ground state has been converged with point group symmetries enabled.

# Sodium dimer
from ase.build import molecule
atoms = molecule('Na2')
atoms.center(vacuum=8.0)

# Poisson solver with multipole corrections up to l=2
poissonsolver = {'name': 'MomentCorrectionPoissonSolver',
                 'moment_corrections': 1 + 3 + 5,
                 'poissonsolver': 'fast'}

# Ground-state calculation
from gpaw.new.ase_interface import GPAW
calc = GPAW(mode='lcao', h=0.3, basis='dzp',
            setups={'Na': '1'},
            poissonsolver=poissonsolver,
            convergence={'density': 1e-12},
            symmetry={'point_group': False})
atoms.calc = calc
energy = atoms.get_potential_energy()
calc.write('gs.gpw', mode='all')

Next we kick the system in the z direction and propagate 3000 steps of 0.001 ASE units. The ASE unit of time is \(Å\sqrt{\mathrm{e/eV}}\), which is about 10.18fs. We open a file and write to it the dipole moments.

  • It is important to explicitly write the kick to the dipole moment file so that the spectrum calculator knows what kind of kick was used. The convenience property \(most_recent_kick\) of the history object can be used to obtain the last kick.

# Time-propagation calculation
from gpaw.external import create_absorption_kick
from gpaw.new.rttddft import RTTDDFT
from gpaw.new.rttddft.writers import DipoleMomentWriter

dt = 1e-3  # Time step in ASE units Å sqrt(u/eV). Rougly equal to 10as

# Read converged ground-state file
td_calc = RTTDDFT.from_file('gs.gpw', td_algorithm='sicn')

# Open dipole moment file
with DipoleMomentWriter('dm.dat') as dmwriter:
    # Optionally, write a comment to signify (re)start
    dmwriter.write_comment(f'Start at {td_calc.time:.8f}')

    # Kick, write a comment about the kick, and write the dipole moment
    kick_potential = create_absorption_kick([0.0, 0.0, 1e-5])
    td_calc.kick(kick_potential)
    dmwriter.write_kick(td_calc.time, kick_potential)
    dmwriter.write_dm(td_calc.time, td_calc.state, td_calc.pot_calc)

    # Propagate for 3000 steps
    for _ in td_calc.ipropagate(dt, 3000):
        dmwriter.write_dm(td_calc.time, td_calc.state, td_calc.pot_calc)

# Save the state for restarting later
td_calc.write('td.gpw')

After the time propagation, the spectrum can be calculated:

# Analyze the results
from gpaw.tddft.spectrum import photoabsorption_spectrum
photoabsorption_spectrum('dm.dat', 'spec.dat')

This example input script can be downloaded here.

Code documentation

This module implements classes for real-time time-dependent density functional theory (rt-TDDFT) calculations.

The main RTTDDFT class is agnostic to the underlying implementation of the wave functions (FD, or LCAO). Instead, the implementation specific functionality is contained in the propagator classes.

class gpaw.new.rttddft.RTTDDFT(state, pot_calc, hamiltonian, history, td_algorithm=None, *, dft_params, world=None)[source]

Real-time time-propagation TDDFT calculator.

Parameters:
  • state (RTTDDFTState) – State containing wave functions and potentials.

  • pot_calc (PotentialCalculator) – Potential calculator.

  • hamiltonian – Time-dependent Hamiltonian object.

  • history (RTTDDFTHistory) – History object.

  • td_algorithm (TDAlgorithmLike) – Propagation algorithm for the state.

  • dft_params (Parameters) – Parameters used in underlying DFT calculation.

property atoms: Atoms

Get ASE atoms object.

classmethod from_dft_calculation(calc, td_algorithm=None)[source]

Set up the RTTDDFT object from a DFT calculation file.

Parameters:
  • filepath – Filename of the DFT calculation file.

  • td_algorithm (TDAlgorithmLike) – Propagation algorithm for the state.

classmethod from_dft_file(filepath, td_algorithm=None, world=None)[source]

Set up the RTTDDFT object from a DFT calculation file.

Parameters:
  • filepath (str) – Filename of the DFT calculation file.

  • td_algorithm (TDAlgorithmLike) – Propagation algorithm for the state.

classmethod from_file(filepath, *, world=None, **kwargs)[source]

Set up the RTTDDFT object from a file.

The file can be a DFT calculation file or a RTTDDFT restart file. This is inferred from the file contents. See from_dft_file() and from_rttddft_file().

Parameters:
  • filepath (str) – Filename.

  • kwargs – Parameters passed to the from_dft_file() if \(filepath\) is a DFT calculation file. No parameters are allowed for RTTDDFT restart files.

classmethod from_rttddft_file(filepath, world=None)[source]

Set up the RTTDDFT object from a restart file.

Parameters:

filepath (str) – Filename of the restart file.

ipropagate(time_step=0.001, maxiter=2000)[source]

Propagate the electronic system.

Parameters:
  • time_step (float) – Time step in ASE time units Å√(u/eV).

  • maxiter (int) – Number of propagation steps.

Yields:

Current time in ASE time units Å√(u/eV) for every step.

kick(potential, nkicks=10)[source]

Kick with any external potential and register in history.

Parameters:
  • potential (ExternalPotential) – External potential.

  • nkicks (int) – Propagate the wave functions nkicks times, using a kick that is scaled down by 1/nkicks. Propagating the kick in several steps improves the accuracy of the propagator.

property time: float

Current simulation time in atomic units.

write(filename)[source]

Write a restart file.

Parameters:

filename (str) – Filename of the restart file.

class gpaw.new.rttddft.RTTDDFTHistory[source]

Representation of the history of a RT-TDDFT calculation. The class stores the current time and the number of propagation steps, as well as a list of previous kicks.

property kicks: list[RTTDDFTKick]

Kicks that have been done.

property niter: int

Number of propagation steps.

propagate(time_step)[source]

Increment the number of propagation steps and simulation time in history.

Parameters:

time_step (float) – Time step in atomic units.

Returns:

The new simulation time in atomic units.

Return type:

float

register_kick(potential, gauge='length')[source]

Store the kick in history.

Parameters:
property time: float

Current simulation time in atomic units.

class gpaw.new.rttddft.history.RTTDDFTHistory[source]

Representation of the history of a RT-TDDFT calculation. The class stores the current time and the number of propagation steps, as well as a list of previous kicks.

property kicks: list[RTTDDFTKick]

Kicks that have been done.

property niter: int

Number of propagation steps.

propagate(time_step)[source]

Increment the number of propagation steps and simulation time in history.

Parameters:

time_step (float) – Time step in atomic units.

Returns:

The new simulation time in atomic units.

Return type:

float

register_kick(potential, gauge='length')[source]

Store the kick in history.

Parameters:
property time: float

Current simulation time in atomic units.

class gpaw.new.rttddft.history.TDAlgorithmLike

Instance of gpaw.new.rttddft.td_algorithm.TDAlgorithm or a string or dict that describes the gpaw.new.rttddft.td_algorithm.TDAlgorithm.

Allowed strings are

Allowed dictionaries are on the form {'name': name, ...} where \(name\) is one of the allowed strings.

class gpaw.new.rttddft.td_algorithm.ECNAlgorithm(implementation='numpy')[source]

Explicit Crank-Nicolson algorithm

Crank-Nicolson propagator, which approximates the time-dependent Hamiltonian to be unchanged during one iteration step.

Parameters:

implementation (str) – Name of wave function propagator implementation

propagate(time_step, state, pot_calc, hamiltonian)[source]

Perform one propagation step, i.e.

  1. Calculate propagator \(U[H(t)]\)

  2. Update wavefunctions \(ψ_n(t+\Delta t) = U[H(t)] ψ_n(t)\)

  3. Update density and hamiltonian \(H(t+dt)\)

\[U(0^+, 0) = \hat{T} \mathrm{exp}\left[ -i S^{-1} \int_t^{t+\Delta t} \mathrm{d}\tau \hat{H}(\tau) \right]\]
todict()[source]
class gpaw.new.rttddft.td_algorithm.SICNAlgorithm(implementation='numpy')[source]

Semi-implicit Crank-Nicolson propagator

Crank-Nicolson propagator, which first approximates the time-dependent Hamiltonian to be unchanged during one iteration step to predict future wavefunctions. Then the approximations for the future wavefunctions are used to approximate the Hamiltonian at the middle of the time step.

Parameters:

implementation (str) – Name of wave function propagator implementation

propagate(time_step, state, pot_calc, hamiltonian)[source]

Perform one propagation step, i.e.

  1. Calculate propagator \(U[H(t)]\)

  2. Update wavefunctions \(ψ_n(t+\Delta t) = U[H(t)] ψ_n(t)\)

  3. Update density and hamiltonian \(H(t+dt)\)

\[U(0^+, 0) = \hat{T} \mathrm{exp}\left[ -i S^{-1} \int_t^{t+\Delta t} \mathrm{d}\tau \hat{H}(\tau) \right]\]
todict()[source]
class gpaw.new.rttddft.td_algorithm.TDAlgorithm(implementation='numpy')[source]

Propagation algorithm for the state

Parameters:

implementation (str) – Name of wave function propagator implementation

get_description()[source]
propagate(time_step, state, pot_calc, hamiltonian)[source]

Perform one propagation step, i.e.

  1. Calculate propagator \(U[H(t)]\)

  2. Update wavefunctions \(ψ_n(t+\Delta t) = U[H(t)] ψ_n(t)\)

  3. Update density and hamiltonian \(H(t+dt)\)

\[U(0^+, 0) = \hat{T} \mathrm{exp}\left[ -i S^{-1} \int_t^{t+\Delta t} \mathrm{d}\tau \hat{H}(\tau) \right]\]
propagate_wfs(time_step, state, hamiltonian)[source]
todict()[source]
update_time_dependent_operators(state, pot_calc)[source]
gpaw.new.rttddft.td_algorithm.create_td_algorithm(name, **kwargs)[source]
class gpaw.new.rttddft.dataclasses.RTTDDFTKick(time, potential, gauge='length')[source]

Class representing an RTTDDFT kick for logging purposes.

class gpaw.new.rttddft.dataclasses.RTTDDFTState(ibzwfs, density, potential, energies)[source]

State of a Kohn-Sham system during RT-TDDFT.

class gpaw.external.ExternalPotential[source]