def setUp(self): UTGroundStateSetup.setUp(self) for virtvar in ['timesteps', 'propagator']: assert getattr(self,virtvar) is not None, 'Virtual "%s"!' % virtvar self.tdname = 'ut_tddft_td_' + self.propagator.lower() self.tdcalc = TDDFT(self.gsname + '.gpw', propagator=self.propagator, txt=self.tdname + '.txt')
def time_propagation(self, filename, kick_strength, time_step, iterations, dipole_moment_file=None, restart_file=None, dump_interval=100, **kwargs): self.td_calc = TDDFT(filename, **kwargs) if kick_strength is not None: self.td_calc.absorption_kick(kick_strength) self.td_calc.hamiltonian.poisson.set_kick(kick_strength) self.td_calc.propagate(time_step, iterations, dipole_moment_file, restart_file, dump_interval)
def setUp(self): UTGroundStateSetup.setUp(self) for virtvar in ["timesteps", "propagator"]: assert getattr(self, virtvar) is not None, 'Virtual "%s"!' % virtvar self.tdname = "ut_tddft_td_" + self.propagator.lower() self.tdcalc = TDDFT(self.gsname + ".gpw", propagator=self.propagator, txt=self.tdname + ".txt")
atoms = molecule('SiH4') atoms.center(vacuum=4.0) # Ground-state calculation calc = GPAW(nbands=7, h=0.4, poissonsolver=PoissonSolver(eps=1e-16), convergence={'density': 1e-8}, xc='GLLBSC', txt='gs.out') atoms.set_calculator(calc) energy = atoms.get_potential_energy() calc.write('gs.gpw', mode='all') # Time-propagation calculation td_calc = TDDFT('gs.gpw', txt='td.out') td_calc.absorption_kick(np.ones(3) * 1e-5) td_calc.propagate(20, 3, 'dm.dat') # Write a restart point td_calc.write('td.gpw', mode='all') # Keep propagating td_calc.propagate(20, 3, 'dm.dat') # Restart from the restart point td_calc = TDDFT('td.gpw', txt='td2.out') td_calc.propagate(20, 3, 'dm.dat') world.barrier() # Check dipole moment file
positions=[(0, 0, 0), (3.0, 0, 0)], pbc=False) atoms.center(vacuum=3.0) # Standard ground state calculation calc = GPAW(nbands=2, h=0.6, setups={'Na': '1'}, poissonsolver=poissonsolver, convergence={'density': density_eps}) atoms.set_calculator(calc) energy = atoms.get_potential_energy() calc.write('na2_gs.gpw', mode='all') # Standard time-propagation initialization time_step = 10.0 iterations = 20 kick_strength = [1.0e-3, 1.0e-3, 0.0] td_calc = TDDFT('na2_gs.gpw') td_calc.absorption_kick(kick_strength=kick_strength) # Create and attach InducedField object frequencies = [1.0, 2.08] # Frequencies of interest in eV folding = 'Gauss' # Folding function width = 0.1 # Line width for folding in eV ind = TDDFTInducedField(paw=td_calc, frequencies=frequencies, folding=folding, width=width, restart_file='na2_td.ind') # Propagate as usual td_calc.propagate(time_step, iterations // 2, 'na2_td_dm.dat', 'na2_td.gpw')
cell_c = np.sum(atoms.get_cell()**2, axis=1)**0.5 N_c = 8 * np.round(cell_c / (0.2 * 8)) calc = GPAW(gpts=N_c, nbands=5, basis='dzp', txt=name + '_gs.txt', eigensolver='rmm-diis') atoms.set_calculator(calc) atoms.get_potential_energy() calc.write(name + '_gs.gpw', mode='all') del atoms, calc time.sleep(10) while not os.path.isfile(name + '_gs.gpw'): print('Node %d waiting for file...' % world.rank) time.sleep(10) world.barrier() tdcalc = TDDFT(name + '_gs.gpw', txt=name + '_td.txt', propagator='EFSICN') ehrenfest = EhrenfestVelocityVerlet(tdcalc) traj = PickleTrajectory(name + '_td.traj', 'w', tdcalc.get_atoms()) t0 = time.time() f = paropen(name + '_td.log', 'w') for i in range(1, niter+1): ehrenfest.propagate(timestep) if i % ndiv == 0: rate = 60 * ndiv / (time.time()-t0) ekin = tdcalc.atoms.get_kinetic_energy() epot = tdcalc.get_td_energy() * Hartree F_av = ehrenfest.F * Hartree / Bohr print('i=%06d (%6.2f min^-1), ekin=%13.9f, epot=%13.9f, etot=%13.9f' % (i, rate, ekin, epot, ekin+epot), file=f) t0 = time.time()
atoms.center(vacuum=6.0) # Larger grid spacing, LDA is ok gs_calc = GPAW(nbands=1, h=0.35, xc='LDA') atoms.set_calculator(gs_calc) e = atoms.get_potential_energy() niter = gs_calc.get_number_of_iterations() gs_calc.write('na2_gs.gpw', 'all') # 16 fs run with 8.0 attosec time step time_step = 8.0 # 8.0 as (1 as = 0.041341 autime)5D iters = 10 # 2000 x 8 as => 16 fs # Weak delta kick to z-direction kick = [0,0,1e-3] # TDDFT calculator td_calc = TDDFT('na2_gs.gpw') # Kick td_calc.absorption_kick(kick) # Propagate td_calc.propagate(time_step, iters, 'na2_dmz.dat', 'na2_td.gpw') # Linear absorption spectrum photoabsorption_spectrum('na2_dmz.dat', 'na2_spectrum_z.dat', width=0.3) iters = 3 # test restart td_rest = TDDFT('na2_td.gpw') td_rest.propagate(time_step, iters, 'na2_dmz2.dat', 'na2_td2.gpw') # test restart
class QSFDTD: def __init__(self, classical_material, atoms, cells, spacings, communicator=serial_comm, remove_moments=(1, 1)): self.td_calc = None # Define classical cell in one of these ways: # 1. [cx, cy, cz] -> vacuum for the quantum grid = 4.0 # 2. ([cx, cy, cz]) -> vacuum = 4.0 # 3. ([cx, cy, cz], vacuum) # 4. ([cx, cy, cz], ([p1x, p1y, p1z], [p2x, p2y, p2z])) where p1 and p2 are corners of the quantum grid if len(cells)==1: # (cell) assert(len(cells[0])==3) cell=np.array(cells[0]) vacuum=4.0 elif len(cells)==3: # [cell.x, cell.y, cell.z] cell=np.array(cells) vacuum=4.0 elif len(cells)==2: # cell + vacuum/corners cell=np.array(cells[0]) if np.array(cells[1]).size==1: vacuum=cells[1] corners=None else: vacuum=None corners=cells[1] else: raise Exception, 'QSFDTD: cells defined incorrectly' # Define spacings in in one of these ways: # 1. (clh, qmh) # 2. clh -> qmh=clh/4 if np.array(spacings).size==1: # clh cl_spacing = spacings qm_spacing = 0.25*cl_spacing elif len(spacings)==2: # (clh, qmh) cl_spacing = spacings[0] qm_spacing = spacings[1] else: raise Exception, 'QSFDTD: spacings defined incorrectly' self.poissonsolver = FDTDPoissonSolver(classical_material = classical_material, cl_spacing = cl_spacing, qm_spacing = qm_spacing, remove_moments = remove_moments, communicator = communicator, cell = cell) self.poissonsolver.set_calculation_mode('iterate') # Quantum system if atoms is not None: assert(len(cells)==2) assert(len(spacings)==2) assert(len(remove_moments)==2) self.atoms = atoms self.atoms.set_cell(cell) if vacuum is not None: # vacuum self.atoms, self.qm_spacing, self.gpts = self.poissonsolver.cut_cell(self.atoms, vacuum=vacuum) else: # corners self.atoms, self.qm_spacing, self.gpts = self.poissonsolver.cut_cell(self.atoms, corners=corners) else: # Dummy quantum system self.atoms = Atoms("H", [0.5*cell], cell=cell) if vacuum is not None: # vacuum self.atoms, self.qm_spacing, self.gpts = self.poissonsolver.cut_cell(self.atoms, vacuum=vacuum) else: # corners self.atoms, self.qm_spacing, self.gpts = self.poissonsolver.cut_cell(self.atoms, corners=corners) del self.atoms[:] def ground_state(self, filename, **kwargs): # GPAW calculator for the ground state self.gs_calc = GPAW(gpts = self.gpts, poissonsolver = self.poissonsolver, **kwargs ) self.atoms.set_calculator(self.gs_calc) self.energy = self.atoms.get_potential_energy() self.write(filename, mode='all') def write(self, filename, **kwargs): if self.td_calc is None: self.gs_calc.write(filename, **kwargs) else: self.td_calc.write(filename, **kwargs) def time_propagation(self, filename, kick_strength, time_step, iterations, dipole_moment_file=None, restart_file=None, dump_interval=100, **kwargs): self.td_calc = TDDFT(filename, **kwargs) if kick_strength is not None: self.td_calc.absorption_kick(kick_strength) self.td_calc.hamiltonian.poisson.set_kick(kick_strength) self.td_calc.propagate(time_step, iterations, dipole_moment_file, restart_file, dump_interval)
from gpaw.tddft import TDDFT from gpaw.inducedfield.inducedfield_fdtd import (FDTDInducedField, calculate_hybrid_induced_field ) from gpaw.inducedfield.inducedfield_tddft import TDDFTInducedField td_calc = TDDFT('td.gpw') # Classical subsystem cl_ind = FDTDInducedField(filename='cl.ind', paw=td_calc) cl_ind.calculate_induced_field(gridrefinement=2) cl_ind.write('cl_field.ind', mode='all') # Quantum subsystem qm_ind = TDDFTInducedField(filename='qm.ind', paw=td_calc) qm_ind.calculate_induced_field(gridrefinement=2) qm_ind.write('qm_field.ind', mode='all') # Total system, interpolate/extrapolate to a grid with spacing h tot_ind = calculate_hybrid_induced_field(cl_ind, qm_ind, h=1.0) tot_ind.write('tot_field.ind', mode='all')
basis='dzp', txt=name + '_gs.txt', eigensolver='rmm-diis') atoms.set_calculator(calc) atoms.get_potential_energy() calc.write(name + '_gs.gpw', mode='all') del atoms, calc time.sleep(10) while not os.path.isfile(name + '_gs.gpw'): print('Node %d waiting for file...' % world.rank) time.sleep(10) world.barrier() tdcalc = TDDFT(name + '_gs.gpw', txt=name + '_td.txt', parallel={'band': 5}, propagator='EFSICN') ehrenfest = EhrenfestVelocityVerlet(tdcalc) traj = Trajectory(name + '_td.traj', 'w', tdcalc.get_atoms()) t0 = time.time() f = paropen(name + '_td.log', 'w') for i in range(1, niter + 1): ehrenfest.propagate(timestep) if i % ndiv == 0: rate = 60 * ndiv / (time.time() - t0) ekin = tdcalc.atoms.get_kinetic_energy() epot = tdcalc.get_td_energy() * Hartree F_av = ehrenfest.F * Hartree / Bohr s = 'i=%06d (%6.2f min^-1), ekin=%13.9f, epot=%13.9f, etot=%13.9f'
from gpaw.tddft import TDDFT from matplotlib import use, patches from matplotlib.pyplot import * from ase.units import Bohr import numpy as np import sys # Initialize TDDFT and QSFDTD td_calc = TDDFT('gs.gpw') def generate_xygrid(d, g, box): vslice = 2 # yx # Determine the array lengths in each dimension ng = d.shape X = None Y = None U = None V = None # Slice data d_slice = np.rollaxis(d, vslice)[g[vslice], :, :] d_proj = np.zeros(d_slice.shape) for ind, val in np.ndenumerate(d_slice): d_proj[ind] = np.where( np.append(np.rollaxis(d, vslice)[:, ind[0], ind[1]], 1.0) != 0)[0][0]
sigma = tar['Width'] except KeyError: timestep = 1 sigma = None omega_w = tar.get('Frequency') gamma_w = tar.get('PhaseFactor') Fnt_wsG = tar.get('FourierTransform') Ant_sG = tar.get('Average') atoms = None del tar gpw_filename = sys.argv[2] assert gpw_filename.endswith('.gpw'), 'Invalid GPW tarfile.' assert os.path.isfile(gpw_filename), 'GPW tarfile not found.' calc = TDDFT(gpw_filename, txt=None) obs = DensityFourierTransform(timestep * autime_to_attosec, omega_w * aufrequency_to_eV, (sigma is not None and sigma \ * aufrequency_to_eV or None)) obs.initialize(calc) atoms = calc.get_atoms() del calc obs.read(ftd_filename, idiotproof=False) try: sys.stdout.write('Select grid refinement [1*/2]: ') gdref = int(sys.stdin.readline().strip()) except: gdref = 1 getall = slice(None) #hack to obtain all frequencies/spins Fnt_wsG = obs.get_fourier_transform(getall, getall, gdref)
atoms = Atoms(symbols='Na2', positions=[(0, 0, 0), (3.0, 0, 0)], pbc=False) atoms.center(vacuum=6.0) # Standard ground state calculation calc = GPAW(nbands=2, h=0.4, setups={'Na': '1'}) atoms.set_calculator(calc) energy = atoms.get_potential_energy() calc.write('na2_gs.gpw', mode='all') # Standard time-propagation initialization time_step = 10.0 iterations = 3000 kick_strength = [1.0e-3, 0.0, 0.0] td_calc = TDDFT('na2_gs.gpw') td_calc.absorption_kick(kick_strength=kick_strength) # Create and attach InducedField object frequencies = [1.0, 2.08] # Frequencies of interest in eV folding = 'Gauss' # Folding function width = 0.1 # Line width for folding in eV ind = TDDFTInducedField(paw=td_calc, frequencies=frequencies, folding=folding, width=width, restart_file='na2_td.ind') # Propagate as usual td_calc.propagate(time_step, iterations, 'na2_td_dm.dat', 'na2_td.gpw')
from ase import Atoms from gpaw import GPAW from gpaw.tddft import TDDFT from gpaw.tddft.abc import LinearAbsorbingBoundary from gpaw.tddft.laser import CWField atoms = Atoms('Be',[(0,0,0)], pbc=False) atoms.center(vacuum=6) calc = GPAW(h=0.35) atoms.set_calculator(calc) atoms.get_potential_energy() calc.write('be_gs.gpw', 'all') td_calc = TDDFT('be_gs.gpw', td_potential = CWField(1e-3, 2.0*np.pi/50.0, 150.0)) td_calc.set_absorbing_boundary(LinearAbsorbingBoundary(5.0, 0.01, atoms.positions.copy())) td_calc.propagate(8.0, 5, 'be_nl_dmz_ipabs_1e-3.dat', 'be_nl_td.gpw') td_rest = TDDFT('be_nl_td.gpw', td_potential = CWField(1e-3, 2.0*np.pi/50.0, 150.0)) td_rest.set_absorbing_boundary(LinearAbsorbingBoundary(5.0, 0.01, atoms.positions.copy())) td_rest.propagate(8.0, 5, 'be_nl_dmz_ipabs_1e-3.dat', 'be_nl_td.gpw')
from gpaw.tddft import TDDFT from gpaw.tddft.ehrenfest import EhrenfestVelocityVerlet import sys d = 4.5 atoms = Atoms('NaCl', [(0,0,0),(0,0,d)]) atoms.center(vacuum=4.5) d = 4.0 atoms.set_positions([(0,0,0),(0,0,d)]) atoms.center() gs_calc = GPAW(nbands=4, gpts=(64,64,96), xc='LDA', setups='hgh') atoms.set_calculator(gs_calc) atoms.get_potential_energy() gs_calc.write('nacl_hgh_gs.gpw', 'all') td_calc = TDDFT('nacl_hgh_gs.gpw', propagator='ETRSCN') evv = EhrenfestVelocityVerlet(td_calc, 0.001) i=0 evv.get_energy() r = evv.x[1][2] - evv.x[0][2] print 'E = ', [i, r, evv.Etot, evv.Ekin, evv.Epot] for i in range(10000): evv.propagate(1.0) evv.get_energy() r = evv.x[1][2] - evv.x[0][2] print 'E = ', [i+1, r, evv.Etot, evv.Ekin, evv.Epot]
from gpaw.tddft import TDDFT, photoabsorption_spectrum from gpaw.inducedfield.inducedfield_tddft import TDDFTInducedField # Calculate photoabsorption spectrum as usual folding = 'Gauss' width = 0.1 e_min = 0.0 e_max = 4.0 photoabsorption_spectrum('na2_td_dm.dat', 'na2_td_spectrum_x.dat', folding=folding, width=width, e_min=e_min, e_max=e_max, delta_e=1e-2) # Load TDDFT object td_calc = TDDFT('na2_td.gpw') # Load InducedField object ind = TDDFTInducedField(filename='na2_td.ind', paw=td_calc) # Calculate induced electric field ind.calculate_induced_field(gridrefinement=2, from_density='comp') # Save induced electric field ind.write('na2_td_field.ind', mode='all')
input_file = name + '_run' + str(run) + '.gpw' traj_file = strbody + '.traj' filename = strbody + '.txt' f = open(filename, "w") Natoms = 106 Nkord = 3 p_bands = 2 print(en, run) #number of iterations and integer divisor to update states every 0.02 fs #ndiv = int(np.ceil(0.01e3 / timestep)) niter = ndiv * int(np.ceil(duration / (ndiv * timestep))) #parallel = { 'band' : p_bands, 'domain' : None, 'sl_auto' : True} #parallel = { 'band' : p_bands, 'domain' : None, 'sl_default' : (4, 4, 64)} parallel = {'band': p_bands, 'domain': None} tdcalc = TDDFT(input_file, solver='CSCG', propagator='EFSICN', parallel=parallel) ##Projectile part proj_idx = Natoms - 1 v = np.zeros((Natoms, 3)) #set all velocity to zero Mproj = tdcalc.atoms.get_masses()[proj_idx] #Mat = [] #vat = np.zeros([12, 3]) #for i in range(0,12): # Mat.append(tdcalc.atoms.get_masses()[i]*amu_to_aumass) #ekin projectile Ekin *= Mproj Ekin = Ekin / Hartree
d = 4.0 atoms = Atoms('NaCl', [(0, 0, 0), (0, 0, d)]) atoms.center(vacuum=4.5) gs_calc = GPAW(nbands=4, eigensolver='cg', gpts=(32, 32, 44), xc='LDA', setups={'Na': '1'}) atoms.set_calculator(gs_calc) atoms.get_potential_energy() gs_calc.write('nacl_gs.gpw', 'all') td_calc = TDDFT('nacl_gs.gpw', propagator='EFSICN') evv = EhrenfestVelocityVerlet(td_calc, 0.001) i = 0 evv.get_energy() r = evv.x[1][2] - evv.x[0][2] # print 'E = ', [i, r, evv.Etot, evv.Ekin, evv.e_coulomb] for i in range(5): evv.propagate(1.0) evv.get_energy() r = evv.x[1][2] - evv.x[0][2] print('E = ', [i + 1, r, evv.Etot, evv.Ekin, evv.e_coulomb]) equal(r, 7.558883144, 1e-6) equal(evv.Etot, -0.1036763317, 1e-7)
atoms.center(vacuum=4.0) # Ground-state calculation calc = GPAW(nbands=7, h=0.4, poissonsolver=PoissonSolver(eps=1e-16), convergence={'density': 1e-8}, xc='GLLBSC', txt='gs.out') atoms.set_calculator(calc) energy = atoms.get_potential_energy() calc.write('gs.gpw', mode='all') fxc = 'LDA' # Time-propagation calculation with linearize_to_fxc() td_calc = TDDFT('gs.gpw', txt='td.out') td_calc.linearize_to_xc(fxc) td_calc.absorption_kick(np.ones(3) * 1e-5) td_calc.propagate(20, 4, 'dm.dat') world.barrier() # Test the absolute values data = np.loadtxt('dm.dat').ravel() if 0: from gpaw.test import print_reference print_reference(data, 'ref', '%.12le') ref = [ 0.0, 1.46915686e-15, -3.289312570937e-14, -2.273046460905e-14, -3.201827522804e-15, 0.82682747, 1.41057108e-15, 6.113786981692e-05, 6.113754003915e-05, 6.113827654045e-05, 1.65365493, 1.69317502e-16,
class UTStaticPropagatorSetup(UTGroundStateSetup): __doc__ = UTGroundStateSetup.__doc__ + """ Propagate electrons with fixed nuclei and verify results.""" #TODO duration = 10.0 #24.0 timesteps = None propagator = None def setUp(self): UTGroundStateSetup.setUp(self) for virtvar in ['timesteps', 'propagator']: assert getattr(self,virtvar) is not None, 'Virtual "%s"!' % virtvar self.tdname = 'ut_tddft_td_' + self.propagator.lower() self.tdcalc = TDDFT(self.gsname + '.gpw', propagator=self.propagator, txt=self.tdname + '.txt') def tearDown(self): del self.tdcalc # ================================= def _test_timestepping(self, t): #XXX DEBUG START if debug and os.path.isfile('%s_%d.gpw' % (self.tdname, t)): return #XXX DEBUG END timestep = self.timesteps[t] self.assertAlmostEqual(self.duration % timestep, 0.0, 12) niter = int(self.duration / timestep) ndiv = 1 #XXX traj = PickleTrajectory('%s_%d.traj' % (self.tdname, t), 'w', self.tdcalc.get_atoms()) t0 = time.time() f = paropen('%s_%d.log' % (self.tdname, t), 'w') print >>f, 'propagator: %s, duration: %6.1f as, timestep: %5.2f as, ' \ 'niter: %d' % (self.propagator, self.duration, timestep, niter) for i in range(1, niter+1): # XXX bare bones propagation without all the nonsense self.tdcalc.propagator.propagate(self.tdcalc.time, timestep * attosec_to_autime) self.tdcalc.time += timestep * attosec_to_autime self.tdcalc.niter += 1 if i % ndiv == 0: rate = 60 * ndiv / (time.time()-t0) ekin = self.tdcalc.atoms.get_kinetic_energy() epot = self.tdcalc.get_td_energy() * Hartree F_av = np.zeros((len(self.tdcalc.atoms), 3)) print >>f, 'i=%06d, time=%6.1f as, rate=%6.2f min^-1, ' \ 'ekin=%13.9f eV, epot=%13.9f eV, etot=%13.9f eV' \ % (i, timestep * i, rate, ekin, epot, ekin + epot) t0 = time.time() # Hack to prevent calls to GPAW::get_potential_energy when saving spa = self.tdcalc.get_atoms() spc = SinglePointCalculator(epot, F_av, None, None, spa) spa.set_calculator(spc) traj.write(spa) f.close() traj.close() self.tdcalc.write('%s_%d.gpw' % (self.tdname, t), mode='all') # Save density and wavefunctions to binary gd, finegd = self.tdcalc.wfs.gd, self.tdcalc.density.finegd if world.rank == 0: big_nt_g = finegd.collect(self.tdcalc.density.nt_g) np.save('%s_%d_nt.npy' % (self.tdname, t), big_nt_g) del big_nt_g big_psit_nG = gd.collect(self.tdcalc.wfs.kpt_u[0].psit_nG) np.save('%s_%d_psit.npy' % (self.tdname, t), big_psit_nG) del big_psit_nG else: finegd.collect(self.tdcalc.density.nt_g) gd.collect(self.tdcalc.wfs.kpt_u[0].psit_nG) world.barrier() def test_timestepping_ref(self): # Reference values for density and wavefunctions (assumed stationary) nt0_g = self.tdcalc.density.nt_g phases_n = self.tdcalc.wfs.kpt_u[0].eps_n * self.duration * attosec_to_autime psit0_nG = np.exp(-1j * phases_n) * self.tdcalc.wfs.kpt_u[0].psit_nG f = paropen('%s_ref.log' % self.tdname, 'w') niters = np.round(self.duration / self.timesteps).astype(int) print >>f, 'propagator: %s, duration: %6.1f as, niters: %s, ' \ % (self.propagator, self.duration, niters.tolist()) for t,timestep in enumerate(self.timesteps): self.assertTrue(os.path.isfile('%s_%d.gpw' % (self.tdname, t))) # Load density and wavefunctions from binary gd, finegd = self.tdcalc.wfs.gd, self.tdcalc.density.finegd nt_g, psit_nG = finegd.empty(), gd.empty(self.nbands, dtype=complex) if world.rank == 0: big_nt_g = np.load('%s_%d_nt.npy' % (self.tdname, t)) finegd.distribute(big_nt_g, nt_g) del big_nt_g big_psit_nG = np.load('%s_%d_psit.npy' % (self.tdname, t)) gd.distribute(big_psit_nG, psit_nG) del big_psit_nG else: finegd.distribute(None, nt_g) gd.distribute(None, psit_nG) # Check loaded density and wavefunctions against reference values dnt = finegd.comm.max(np.abs(nt_g - nt0_g).max()) dpsit = gd.comm.max(np.abs(psit_nG - psit0_nG).max()) print >>f, 't=%d, timestep: %5.2f as, dnt: %16.13f, ' \ 'dpsit: %16.13f' % (t, timestep, dnt, dpsit) snt, spsit = {'SITE': (5,4)}.get(self.propagator, (7,5)) #self.assertAlmostEqual(dnt, 0, snt, 't=%d, timestep: ' \ # '%5.2f as, dnt: %g, digits: %d' % (t, timestep, dnt, snt)) #self.assertAlmostEqual(dpsit, 0, spsit, 't=%d, timestep: ' \ # '%5.2f as, dpsit=%g, digits: %d' % (t, timestep, dpsit, spsit)) f.close()
import numpy as np from ase import Atoms from gpaw import GPAW from gpaw.tddft import TDDFT from gpaw.tddft.abc import LinearAbsorbingBoundary from gpaw.tddft.laser import CWField atoms = Atoms('Be', [(0, 0, 0)], pbc=False) atoms.center(vacuum=6) calc = GPAW(h=0.35) atoms.set_calculator(calc) atoms.get_potential_energy() calc.write('be_gs.gpw', 'all') td_calc = TDDFT('be_gs.gpw', td_potential=CWField(1e-3, 2.0 * np.pi / 50.0, 150.0)) td_calc.set_absorbing_boundary( LinearAbsorbingBoundary(5.0, 0.01, atoms.positions.copy())) td_calc.propagate(8.0, 5, 'be_nl_dmz_ipabs_1e-3.dat', 'be_nl_td.gpw') td_rest = TDDFT('be_nl_td.gpw', td_potential=CWField(1e-3, 2.0 * np.pi / 50.0, 150.0)) td_rest.set_absorbing_boundary( LinearAbsorbingBoundary(5.0, 0.01, atoms.positions.copy())) td_rest.propagate(8.0, 5, 'be_nl_dmz_ipabs_1e-3.dat', 'be_nl_td.gpw')
from gpaw.tddft import TDDFT from gpaw.inducedfield.inducedfield_tddft import TDDFTInducedField # Load TDDFT object td_calc = TDDFT('na2_td.gpw') # Load and attach InducedField object ind = TDDFTInducedField(filename='na2_td.ind', paw=td_calc, restart_file='na2_td.ind') # Continue propagation as usual time_step = 20.0 iterations = 250 td_calc.propagate(time_step, iterations, 'na2_td_dm.dat', 'na2_td.gpw') # Save TDDFT and InducedField objects td_calc.write('na2_td.gpw', mode='all') ind.write('na2_td.ind')
calc = GPAW(name + '_es.gpw', txt=name + '_esx.txt', parallel={'band': 1}) calc.set_positions() dscf_collapse_orbitals(calc) calc.write(name + '_esx.gpw', mode='all') del calc time.sleep(10) while not os.path.isfile(name + '_esx.gpw'): print('Node %d waiting for %s...' % (world.rank, name + '_esx.gpw')) time.sleep(10) world.barrier() tdcalc = TDDFT(name + '_esx.gpw', txt=name + '_td.txt', propagator='EFSICN') ehrenfest = EhrenfestVelocityVerlet(tdcalc) traj = PickleTrajectory(name + '_td.traj', 'w', tdcalc.get_atoms()) t0 = time.time() f = paropen(name + '_td.log', 'w') for i in range(1, niter + 1): ehrenfest.propagate(timestep) if i % ndiv == 0: rate = 60 * ndiv / (time.time() - t0) ekin = tdcalc.atoms.get_kinetic_energy() epot = tdcalc.get_td_energy() * Hartree F_av = ehrenfest.F * Hartree / Bohr print(
# Test floating point arithmetic errors equal(gs_calc.hamiltonian.poisson.shift_indices_1, [4, 4, 10], 0) equal(gs_calc.hamiltonian.poisson.shift_indices_2, [8, 8, 16], 0) # Save state gs_calc.write('gs.gpw', 'all') classical_material = None gs_calc = None # Initialize TDDFT and FDTD kick = [0.0, 0.0, 1.0e-3] time_step = 10.0 iterations = 10 td_calc = TDDFT('gs.gpw') td_calc.absorption_kick(kick_strength=kick) td_calc.hamiltonian.poisson.set_kick(kick) # Attach InducedFields to the calculation frequencies = [2.05, 4.0] width = 0.15 cl_ind = FDTDInducedField(paw=td_calc, frequencies=frequencies, width=width) qm_ind = TDDFTInducedField(paw=td_calc, frequencies=frequencies, width=width) # Propagate TDDFT and FDTD td_calc.propagate(time_step, iterations // 2, 'dm.dat', 'td.gpw') td_calc.write('td.gpw', 'all') cl_ind.write('cl.ind') qm_ind.write('qm.ind') td_calc = None
class QSFDTD: def __init__(self, classical_material, atoms, cells, spacings, communicator=serial_comm, remove_moments=(1, 1)): self.td_calc = None # Define classical cell in one of these ways: # 1. [cx, cy, cz] -> vacuum for the quantum grid = 4.0 # 2. ([cx, cy, cz]) -> vacuum = 4.0 # 3. ([cx, cy, cz], vacuum) # 4. ([cx, cy, cz], ([p1x, p1y, p1z], [p2x, p2y, p2z])) # where p1 and p2 are corners of the quantum grid if len(cells) == 1: # (cell) assert (len(cells[0]) == 3) cell = np.array(cells[0]) vacuum = 4.0 elif len(cells) == 3: # [cell.x, cell.y, cell.z] cell = np.array(cells) vacuum = 4.0 elif len(cells) == 2: # cell + vacuum/corners cell = np.array(cells[0]) if np.array(cells[1]).size == 1: vacuum = cells[1] corners = None else: vacuum = None corners = cells[1] else: raise Exception('QSFDTD: cells defined incorrectly') # Define spacings in in one of these ways: # 1. (clh, qmh) # 2. clh -> qmh=clh/4 if np.array(spacings).size == 1: # clh cl_spacing = spacings qm_spacing = 0.25 * cl_spacing elif len(spacings) == 2: # (clh, qmh) cl_spacing = spacings[0] qm_spacing = spacings[1] else: raise Exception('QSFDTD: spacings defined incorrectly') self.poissonsolver = FDTDPoissonSolver( classical_material=classical_material, cl_spacing=cl_spacing, qm_spacing=qm_spacing, remove_moments=remove_moments, communicator=communicator, cell=cell) self.poissonsolver.set_calculation_mode('iterate') # Quantum system if atoms is not None: assert (len(cells) == 2) assert (len(spacings) == 2) assert (len(remove_moments) == 2) self.atoms = atoms self.atoms.set_cell(cell) if vacuum is not None: # vacuum self.atoms, self.qm_spacing, self.gpts = \ self.poissonsolver.cut_cell(self.atoms, vacuum=vacuum) else: # corners self.atoms, self.qm_spacing, self.gpts = \ self.poissonsolver.cut_cell(self.atoms, corners=corners) else: # Dummy quantum system self.atoms = Atoms('H', [0.5 * cell], cell=cell) if vacuum is not None: # vacuum self.atoms, self.qm_spacing, self.gpts = \ self.poissonsolver.cut_cell(self.atoms, vacuum=vacuum) else: # corners self.atoms, self.qm_spacing, self.gpts = \ self.poissonsolver.cut_cell(self.atoms, corners=corners) del self.atoms[:] def ground_state(self, filename, **kwargs): # GPAW calculator for the ground state self.gs_calc = GPAW(gpts=self.gpts, poissonsolver=self.poissonsolver, **kwargs) self.atoms.set_calculator(self.gs_calc) self.energy = self.atoms.get_potential_energy() self.write(filename, mode='all') def write(self, filename, **kwargs): if self.td_calc is None: self.gs_calc.write(filename, **kwargs) else: self.td_calc.write(filename, **kwargs) def time_propagation(self, filename, kick_strength, time_step, iterations, dipole_moment_file=None, restart_file=None, dump_interval=100, **kwargs): self.td_calc = TDDFT(filename, **kwargs) if kick_strength is not None: self.td_calc.absorption_kick(kick_strength) self.td_calc.hamiltonian.poisson.set_kick(kick_strength) self.td_calc.propagate(time_step, iterations, dipole_moment_file, restart_file, dump_interval)
# Initialize GPAW gs_calc = GPAW(gpts=gpts, eigensolver='cg', nbands=-2, poissonsolver=poissonsolver) atoms.set_calculator(gs_calc) # Ground state energy = atoms.get_potential_energy() # Save state gs_calc.write('gs.%s.gpw' % tag, 'all') # Initialize TDDFT and FDTD td_calc = TDDFT('gs.%s.gpw' % tag) td_calc.absorption_kick(kick_strength=kick) td_calc.hamiltonian.poisson.set_kick(kick) # Propagate TDDFT and FDTD td_calc.propagate(time_step, 50, 'dm.%s.dat' % tag, 'td.%s.gpw' % tag) # Test ref_cl_dipole_moment = [2.72623607e-02, 1.98393701e-09, -1.98271199e-09] ref_qm_dipole_moment = [1.44266213e-02, 1.04985435e-09, -1.04920610e-09] tol = 0.0001 equal(td_calc.get_dipole_moment(), ref_qm_dipole_moment, tol) equal(td_calc.hamiltonian.poisson.get_dipole_moment(), ref_cl_dipole_moment, tol)
# Test floating point arithmetic errors equal(gs_calc.hamiltonian.poisson.shift_indices_1, [4, 4, 10], 0) equal(gs_calc.hamiltonian.poisson.shift_indices_2, [8, 8, 16], 0) # Save state gs_calc.write('gs.gpw', 'all') classical_material = None gs_calc = None # Initialize TDDFT and FDTD kick = [0.0, 0.0, 1.0e-3] time_step = 10.0 max_time = 100 # 0.1 fs td_calc = TDDFT('gs.gpw') td_calc.absorption_kick(kick_strength=kick) td_calc.hamiltonian.poisson.set_kick(kick) # Propagate TDDFT and FDTD td_calc.propagate(time_step, max_time / time_step / 2, 'dm.dat', 'td.gpw') td_calc2 = TDDFT('td.gpw') td_calc2.propagate(time_step, max_time / time_step / 2, 'dm.dat', 'td.gpw') # Test ref_cl_dipole_moment = [5.25374117e-14, 5.75811267e-14, 3.08349334e-02] ref_qm_dipole_moment = [1.78620337e-11, -1.57782578e-11, 5.21368300e-01] #print("ref_cl_dipole_moment = %s" % td_calc2.hamiltonian.poisson.get_classical_dipole_moment()) #print("ref_qm_dipole_moment = %s" % td_calc2.hamiltonian.poisson.get_quantum_dipole_moment())
class UTStaticPropagatorSetup(UTGroundStateSetup): __doc__ = UTGroundStateSetup.__doc__ + """ Propagate electrons with fixed nuclei and verify results.""" #TODO duration = 10.0 #24.0 timesteps = None propagator = None def setUp(self): UTGroundStateSetup.setUp(self) for virtvar in ['timesteps', 'propagator']: assert getattr(self, virtvar) is not None, 'Virtual "%s"!' % virtvar self.tdname = 'ut_tddft_td_' + self.propagator.lower() self.tdcalc = TDDFT(self.gsname + '.gpw', propagator=self.propagator, txt=self.tdname + '.txt') def tearDown(self): del self.tdcalc # ================================= def _test_timestepping(self, t): #XXX DEBUG START if debug and os.path.isfile('%s_%d.gpw' % (self.tdname, t)): return #XXX DEBUG END timestep = self.timesteps[t] self.assertAlmostEqual(self.duration % timestep, 0.0, 12) niter = int(self.duration / timestep) ndiv = 1 #XXX traj = PickleTrajectory('%s_%d.traj' % (self.tdname, t), 'w', self.tdcalc.get_atoms()) t0 = time.time() f = paropen('%s_%d.log' % (self.tdname, t), 'w') print('propagator: %s, duration: %6.1f as, timestep: %5.2f as, ' \ 'niter: %d' % (self.propagator, self.duration, timestep, niter), file=f) for i in range(1, niter + 1): # XXX bare bones propagation without all the nonsense self.tdcalc.propagator.propagate(self.tdcalc.time, timestep * attosec_to_autime) self.tdcalc.time += timestep * attosec_to_autime self.tdcalc.niter += 1 if i % ndiv == 0: rate = 60 * ndiv / (time.time() - t0) ekin = self.tdcalc.atoms.get_kinetic_energy() epot = self.tdcalc.get_td_energy() * Hartree F_av = np.zeros((len(self.tdcalc.atoms), 3)) print('i=%06d, time=%6.1f as, rate=%6.2f min^-1, ' \ 'ekin=%13.9f eV, epot=%13.9f eV, etot=%13.9f eV' \ % (i, timestep * i, rate, ekin, epot, ekin + epot), file=f) t0 = time.time() # Hack to prevent calls to GPAW::get_potential_energy when saving spa = self.tdcalc.get_atoms() spc = SinglePointCalculator(epot, F_av, None, None, spa) spa.set_calculator(spc) traj.write(spa) f.close() traj.close() self.tdcalc.write('%s_%d.gpw' % (self.tdname, t), mode='all') # Save density and wavefunctions to binary gd, finegd = self.tdcalc.wfs.gd, self.tdcalc.density.finegd if world.rank == 0: big_nt_g = finegd.collect(self.tdcalc.density.nt_g) np.save('%s_%d_nt.npy' % (self.tdname, t), big_nt_g) del big_nt_g big_psit_nG = gd.collect(self.tdcalc.wfs.kpt_u[0].psit_nG) np.save('%s_%d_psit.npy' % (self.tdname, t), big_psit_nG) del big_psit_nG else: finegd.collect(self.tdcalc.density.nt_g) gd.collect(self.tdcalc.wfs.kpt_u[0].psit_nG) world.barrier() def test_timestepping_ref(self): # Reference values for density and wavefunctions (assumed stationary) nt0_g = self.tdcalc.density.nt_g phases_n = self.tdcalc.wfs.kpt_u[ 0].eps_n * self.duration * attosec_to_autime psit0_nG = np.exp(-1j * phases_n) * self.tdcalc.wfs.kpt_u[0].psit_nG f = paropen('%s_ref.log' % self.tdname, 'w') niters = np.round(self.duration / self.timesteps).astype(int) print('propagator: %s, duration: %6.1f as, niters: %s, ' \ % (self.propagator, self.duration, niters.tolist()), file=f) for t, timestep in enumerate(self.timesteps): self.assertTrue(os.path.isfile('%s_%d.gpw' % (self.tdname, t))) # Load density and wavefunctions from binary gd, finegd = self.tdcalc.wfs.gd, self.tdcalc.density.finegd nt_g, psit_nG = finegd.empty(), gd.empty(self.nbands, dtype=complex) if world.rank == 0: big_nt_g = np.load('%s_%d_nt.npy' % (self.tdname, t)) finegd.distribute(big_nt_g, nt_g) del big_nt_g big_psit_nG = np.load('%s_%d_psit.npy' % (self.tdname, t)) gd.distribute(big_psit_nG, psit_nG) del big_psit_nG else: finegd.distribute(None, nt_g) gd.distribute(None, psit_nG) # Check loaded density and wavefunctions against reference values dnt = finegd.comm.max(np.abs(nt_g - nt0_g).max()) dpsit = gd.comm.max(np.abs(psit_nG - psit0_nG).max()) print('t=%d, timestep: %5.2f as, dnt: %16.13f, ' \ 'dpsit: %16.13f' % (t, timestep, dnt, dpsit), file=f) snt, spsit = {'SITE': (5, 4)}.get(self.propagator, (7, 5)) #self.assertAlmostEqual(dnt, 0, snt, 't=%d, timestep: ' \ # '%5.2f as, dnt: %g, digits: %d' % (t, timestep, dnt, snt)) #self.assertAlmostEqual(dpsit, 0, spsit, 't=%d, timestep: ' \ # '%5.2f as, dpsit=%g, digits: %d' % (t, timestep, dpsit, spsit)) f.close()
Ekin = 40e3 # kinetic energy of the ion (in eV) # Adapted to the ion energy; here 4 as (probably too large!) timestep = 16.0 * np.sqrt(10e3 / Ekin) ekin_str = '_ek' + str(int(Ekin / 1000)) + 'k' strbody = name + ekin_str traj_file = strbody + '.traj' # The parallelization options should match the number of cores, here 8. p_bands = 2 # number of bands to parallelise over dom_dc = (2, 2, 4) # domain decomposition for parallelization parallel = {'band': p_bands, 'domain': dom_dc} tdcalc = TDDFT(name + '.gpw', propagator='EFSICN', solver='BiCGStab', txt=strbody + '_td.txt', parallel=parallel) proj_idx = 50 # atomic index of the projectile delta_stop = 5.0 / Bohr # stop condition when ion is within 5 A of boundary. # Setting the initial velocity according to the kinetic energy. amu_to_aumass = _amu / _me Mproj = tdcalc.atoms.get_masses()[proj_idx] * amu_to_aumass Ekin *= 1 / Hartree v = np.zeros((proj_idx + 1, 3)) v[proj_idx, 2] = -np.sqrt((2 * Ekin) / Mproj) * Bohr / AUT tdcalc.atoms.set_velocities(v) evv = EhrenfestVelocityVerlet(tdcalc)
from ase.io import Trajectory from ase.parallel import parprint name = 'h2_diss' # Ehrenfest simulation parameters timestep = 10.0 # timestep given in attoseconds ndiv = 10 # write trajectory every 10 timesteps niter = 500 # run for 500 timesteps # TDDFT calculator with an external potential emulating an intense # harmonic laser field aligned (CWField uses by default the z axis) # along the H2 molecular axis. tdcalc = TDDFT(name + '_gs.gpw', txt=name + '_td.txt', propagator='EFSICN', solver='BiCGStab', td_potential=CWField(1000 * Hartree, 1 * AUT, 10)) # For Ehrenfest dynamics, we use this object for the Velocity Verlet dynamics. ehrenfest = EhrenfestVelocityVerlet(tdcalc) # Trajectory to save the dynamics. traj = Trajectory(name + '_td.traj', 'w', tdcalc.get_atoms()) # Propagates the dynamics for niter timesteps. for i in range(1, niter + 1): ehrenfest.propagate(timestep) if tdcalc.atoms.get_distance(0, 1) > 2.0: # Stop simulation if H-H distance is greater than 2 A
atoms.center(vacuum=6.0) # Larger grid spacing, LDA is ok gs_calc = GPAW(nbands=1, h=0.35, xc='LDA', setups={'Na': '1'}) atoms.set_calculator(gs_calc) e = atoms.get_potential_energy() niter = gs_calc.get_number_of_iterations() gs_calc.write('na2_gs.gpw', 'all') # 16 fs run with 8.0 attosec time step time_step = 8.0 # 8.0 as (1 as = 0.041341 autime)5D iters = 10 # 2000 x 8 as => 16 fs # Weak delta kick to z-direction kick = [0, 0, 1e-3] # TDDFT calculator td_calc = TDDFT('na2_gs.gpw') # Kick td_calc.absorption_kick(kick) # Propagate td_calc.propagate(time_step, iters, 'na2_dmz.dat', 'na2_td.gpw') # Linear absorption spectrum photoabsorption_spectrum('na2_dmz.dat', 'na2_spectrum_z.dat', width=0.3) iters = 3 # test restart td_rest = TDDFT('na2_td.gpw') td_rest.propagate(time_step, iters, 'na2_dmz2.dat', 'na2_td2.gpw') # test restart td_rest = TDDFT('na2_td.gpw', solver='BiCGStab')
# Initialize GPAW gs_calc = GPAW(gpts = gpts, eigensolver = 'cg', nbands = -2, poissonsolver = poissonsolver) atoms.set_calculator(gs_calc) # Ground state energy = atoms.get_potential_energy() # Save state gs_calc.write('gs.%s.gpw' % tag, 'all') # Initialize TDDFT and FDTD td_calc = TDDFT('gs.%s.gpw' % tag) td_calc.absorption_kick(kick_strength=kick) td_calc.hamiltonian.poisson.set_kick(kick) # Propagate TDDFT and FDTD td_calc.propagate(time_step, 50, 'dm.%s.dat' % tag, 'td.%s.gpw' % tag) # Test ref_cl_dipole_moment = [ 2.72623607e-02, 1.98393701e-09, -1.98271199e-09 ] ref_qm_dipole_moment = [ 1.44266213e-02, 1.04985435e-09, -1.04920610e-09 ] tol = 0.0001 equal(td_calc.get_dipole_moment(), ref_qm_dipole_moment, tol)