# 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') # Save TDDFT and InducedField objects td_calc.write('na2_td.gpw', mode='all') ind.write('na2_td.ind') ind.paw = None # Restart and continue 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 td_calc.propagate(time_step, iterations // 2, 'na2_td_dm.dat', 'na2_td.gpw') # Calculate induced electric field
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) traj = Trajectory(traj_file, 'w', tdcalc.get_atoms()) trajdiv = 1 # number of timesteps between trajectory images densdiv = 10 # number of timesteps between saved electron densities niters = 100 # total number of timesteps to propagate for i in range(niters): # Stopping condition when projectile z coordinate passes threshold if evv.x[proj_idx, 2] < delta_stop: tdcalc.write(strbody + '_end.gpw', mode='all') break # Saving trajectory file every trajdiv timesteps if i % trajdiv == 0: F_av = evv.F * Hartree / Bohr # forces converted from atomic units v_av = evv.v * Bohr / AUT # velocities converted from atomic units epot = tdcalc.get_td_energy() * Hartree # energy atoms = tdcalc.get_atoms().copy() atoms.set_velocities(v_av) traj.write(atoms, energy=epot, forces=F_av) # Saving electron density every densdiv timesteps if (i != 0 and i % densdiv == 0): tdcalc.write(strbody + '_step' + str(i) + '.gpw')
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()
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()
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 cl_ind.paw = None qm_ind.paw = None cl_ind = None qm_ind = None # Restart td_calc = TDDFT('td.gpw') cl_ind = FDTDInducedField(filename='cl.ind', paw=td_calc) qm_ind = TDDFTInducedField(filename='qm.ind', paw=td_calc) td_calc.propagate(time_step, iterations // 2, 'dm.dat', 'td.gpw') td_calc.write('td.gpw', 'all') cl_ind.write('cl.ind')
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')