if hasattr(obj, 'diagonalize'): el.diagonalize() # print "*************** obj, len(obj)", obj.__name__, len(el) assert len(el) == 4 el = obj(calc, energy_range=11.5, txt=txt) # print "*************** obj, len(obj)", obj.__name__, len(el) if hasattr(obj, 'diagonalize'): el.diagonalize() assert len(el) == 18 if hasattr(obj, 'diagonalize'): el.diagonalize(energy_range=8) assert len(el) == 4 lr = LrTDDFT(calc, nspins=2) lr.write('lrtddft3.dat.gz') lr.diagonalize() world.barrier() # This is done to test if writing and reading again yields the same result lr2 = LrTDDFT('lrtddft3.dat.gz') lr2.diagonalize() # Unfortunately not all of the lrtddft code is parallel if rank == 0: Epeak = 19.5# The peak we want to investigate (this is alone) Elist = np.asarray([lrsingle.get_energy() * Hartree for lrsingle in lr]) n = np.argmin(np.abs(Elist - Epeak)) # Index of the peak E = lr[n].get_energy() * Hartree osz = lr[n].get_oscillator_strength()
parallel={'domain': mpi.size}, xc='PBE', txt='CO-m.txt', spinpol=True) m = atoms.copy() m.set_initial_magnetic_moments([-1,1]) m.set_calculator(m_c) m.get_potential_energy() d_c = GPAW(gpts=N_c, nbands=16, mixer=MixerDif(0.1, 5, weight=100.0), convergence={'bands':10}, parallel={'domain': mpi.size}, xc='PBE', txt='CO-d.txt', spinpol=True) d = atoms.copy() d.set_initial_magnetic_moments([-1,1]) d_c.set(charge=1) d.set_calculator(d_c) d.get_potential_energy() istart=0 # band index of the first occ. band to consider jend=15 # band index of the last unocc. band to consider d_lr = LrTDDFT(d_c, xc='PBE', nspins=2 , istart=istart, jend=jend) d_lr.diagonalize() pes = TDDFTPES(m_c, d_lr, d_c) pes.save_folded_pes('CO-td.dat', folding=None) pes = DOSPES(m_c, d_c, shift=True) pes.save_folded_pes('CO-dos.dat', folding=None)
parallel={'domain': mpi.size}, xc='PBE', txt='CO-m.txt', spinpol=True) m = atoms.copy() m.set_initial_magnetic_moments([-1,1]) m.set_calculator(m_c) m.get_potential_energy() d_c = GPAW(gpts=N_c, nbands=16, mixer=MixerDif(0.1, 5, weight=100.0), convergence={'bands':10}, parallel={'domain': mpi.size}, xc='PBE', txt='CO-d.txt', spinpol=True) d = atoms.copy() d.set_initial_magnetic_moments([-1,1]) d_c.set(charge=1) d.set_calculator(d_c) d.get_potential_energy() istart=0 # band index of the first occ. band to consider jend=15 # band index of the last unocc. band to consider d_lr = LrTDDFT(d_c, xc='PBE', nspins=2 , istart=istart, jend=jend) d_lr.diagonalize() pes = TDDFTPES(m_c, d_lr, d_c) pes.save_folded_pes('CO-td.dat', folding=None) pes = DOSPES(m_c, d_c) pes.save_folded_pes('CO-dos.dat', folding=None)
from gpaw import restart from gpaw.lrtddft import LrTDDFT, photoabsorption_spectrum atoms, calc = restart('na2_gs_unocc.gpw') # Calculate the omega matrix lr = LrTDDFT(calc, xc='LDA', jend=5) # Use only 5 unoccupied states # Save the omega matrix lr.write('Omega_Na2.gz') # Diagonalize the matrix lr.diagonalize() # Analyse 5 lowest excitations lr.analyse(range(5)) photoabsorption_spectrum(lr, 'Na2_spectrum.dat', e_min=0.0, e_max=10)
if not io_only: R=0.7 # approx. experimental bond length a = 3.0 c = 4.0 H2 = Atoms([Atom('H', (a / 2, a / 2, (c - R) / 2)), Atom('H', (a / 2, a / 2, (c + R) / 2))], cell=(a, a, c)) calc = GPAW(xc='PBE', nbands=3, spinpol=False, txt=txt) H2.set_calculator(calc) H2.get_potential_energy() xc='LDA' # without spin lr = LrTDDFT(calc, xc=xc) lr.diagonalize() t1 = lr[0] lr_calc = lr ex = ExcitedState(lr, 0) den = ex.get_pseudo_density() * Bohr**3 # course grids for finegrid in [1,0]: lr = LrTDDFT(calc, xc=xc, finegrid=finegrid) lr.diagonalize() t3 = lr[0] parprint('finegrid, t1, t3=', finegrid, t1 ,t3) equal(t1.get_energy(), t3.get_energy(), 5.e-4) # with spin
class ExcitedState(GPAW): def __init__(self, lrtddft=None, index=0, d=0.001, txt=None, parallel=0, communicator=None, name=None, restart=None): """ExcitedState object. parallel: Can be used to parallelize the numerical force calculation over images. """ self.timer = Timer() self.atoms = None if isinstance(index, int): self.index = UnconstraintIndex(index) else: self.index = index self.results = {} self.results['forces'] = None self.results['energy'] = None if communicator is None: try: communicator = lrtddft.calculator.wfs.world except: communicator = mpi.world self.world = communicator if restart is not None: self.read(restart) if txt is None: self.txt = self.lrtddft.txt else: self.txt = convert_string_to_fd(txt, self.world) if lrtddft is not None: self.lrtddft = lrtddft self.calculator = self.lrtddft.calculator self.atoms = self.calculator.atoms self.parameters = self.calculator.parameters if txt is None: self.txt = self.lrtddft.txt else: self.txt = convert_string_to_fd(txt, self.world) self.d = d self.parallel = parallel self.name = name self.log = GPAWLogger(self.world) self.log.fd = self.txt self.reader = None self.calculator.log.fd = self.txt self.log('#', self.__class__.__name__, __version__) self.log('#', self.index) if name: self.log('name=' + name) self.log('# Force displacement:', self.d) self.log def __del__(self): self.timer.write(self.log.fd) def set(self, **kwargs): self.calculator.set(**kwargs) def set_positions(self, atoms): """Update the positions of the atoms.""" self.atoms = atoms.copy() self.results['forces'] = None self.results['energy'] = None def write(self, filename, mode=''): try: os.makedirs(filename) except OSError as exception: if exception.errno != errno.EEXIST: raise self.calculator.write(filename=filename + '/' + filename, mode=mode) self.lrtddft.write(filename=filename + '/' + filename + '.lr.dat.gz', fh=None) f = open(filename + '/' + filename + '.exst', 'w') f.write('# ' + self.__class__.__name__ + __version__ + '\n') f.write('Displacement: {0}'.format(self.d) + '\n') f.write('Index: ' + self.index.__class__.__name__ + '\n') for k, v in self.index.__dict__.items(): f.write('{0}, {1}'.format(k, v) + '\n') f.close() mpi.world.barrier() def read(self, filename): self.lrtddft = LrTDDFT(filename + '/' + filename + '.lr.dat.gz') self.atoms, self.calculator = restart( filename + '/' + filename, communicator=self.world) E0 = self.calculator.get_potential_energy() f = open(filename + '/' + filename + '.exst', 'r') f.readline() self.d = f.readline().replace('\n', '').split()[1] indextype = f.readline().replace('\n', '').split()[1] if indextype == 'UnconstraintIndex': iex = int(f.readline().replace('\n', '').split()[1]) self.index = UnconstraintIndex(iex) else: direction = f.readline().replace('\n', '').split()[1] if direction in [str(0), str(1), str(2)]: direction = int(direction) else: direction = None val = f.readline().replace('\n', '').split() if indextype == 'MinimalOSIndex': self.index = MinimalOSIndex(float(val[1]), direction) else: emin = float(val[2]) emax = float(val[3].replace(']', '')) self.index = MaximalOSIndex([emin, emax], direction) index = self.index.apply(self.lrtddft) self.results['energy'] = E0 + self.lrtddft[index].energy * Hartree self.lrtddft.set_calculator(self.calculator) def calculation_required(self, atoms, quantities): if len(quantities) == 0: return False if self.atoms is None: return True elif (len(atoms) != len(self.atoms) or (atoms.get_atomic_numbers() != self.atoms.get_atomic_numbers()).any() or (atoms.get_initial_magnetic_moments() != self.atoms.get_initial_magnetic_moments()).any() or (atoms.get_cell() != self.atoms.get_cell()).any() or (atoms.get_pbc() != self.atoms.get_pbc()).any()): return True elif (atoms.get_positions() != self.atoms.get_positions()).any(): return True for quantity in ['energy', 'forces']: if quantity in quantities: quantities.remove(quantity) if self.results[quantity] is None: return True return len(quantities) > 0 def check_state(self, atoms, tol=1e-15): system_changes = GPAW.check_state(self.calculator, atoms, tol) return system_changes def get_potential_energy(self, atoms=None, force_consistent=None): """Evaluate potential energy for the given excitation.""" if atoms is None: atoms = self.atoms if self.calculation_required(atoms, ['energy']): self.results['energy'] = self.calculate(atoms) return self.results['energy'] def calculate(self, atoms): """Evaluate your energy if needed.""" self.set_positions(atoms) self.calculator.calculate(atoms) E0 = self.calculator.get_potential_energy() atoms.set_calculator(self) if hasattr(self, 'density'): del(self.density) self.lrtddft.forced_update() self.lrtddft.diagonalize() index = self.index.apply(self.lrtddft) energy = E0 + self.lrtddft[index].energy * Hartree self.log('--------------------------') self.log('Excited state') self.log(self.index) self.log('Energy: {0}'.format(energy)) self.log() return energy def get_forces(self, atoms=None, save=False): """Get finite-difference forces If save = True, restartfiles for every displacement are given """ if atoms is None: atoms = self.atoms if self.calculation_required(atoms, ['forces']): atoms.set_calculator(self) # do the ground state calculation to set all # ranks to the same density to start with E0 = self.calculate(atoms) finite = FiniteDifference( atoms=atoms, propertyfunction=atoms.get_potential_energy, save=save, name="excited_state", ending='.gpw', d=self.d, parallel=self.parallel) F_av = finite.run() self.set_positions(atoms) self.results['energy'] = E0 self.results['forces'] = F_av if self.txt: self.log('Excited state forces in eV/Ang:') symbols = self.atoms.get_chemical_symbols() for a, symbol in enumerate(symbols): self.log(('%3d %-2s %10.5f %10.5f %10.5f' % ((a, symbol) + tuple(self.results['forces'][a])))) return self.results['forces'] def forces_indexn(self, index): """ If restartfiles are created from the force calculation, this function allows the calculation of forces for every excited state index. """ atoms = self.atoms def reforce(self, name): excalc = ExcitedState(index=index, restart=name) return excalc.get_potential_energy() fd = FiniteDifference( atoms=atoms, save=True, propertyfunction=self.atoms.get_potential_energy, name="excited_state", ending='.gpw', d=self.d, parallel=0) atoms.set_calculator(self) return fd.restart(reforce) def get_stress(self, atoms): """Return the stress for the current state of the Atoms.""" raise NotImplementedError def initialize_density(self, method='dipole'): if hasattr(self, 'density') and self.density.method == method: return gsdensity = self.calculator.density lr = self.lrtddft self.density = ExcitedStateDensity( gsdensity.gd, gsdensity.finegd, lr.kss.npspins, gsdensity.charge, method=method, redistributor=gsdensity.redistributor) index = self.index.apply(self.lrtddft) self.density.initialize(self.lrtddft, index) self.density.update(self.calculator.wfs) def get_pseudo_density(self, **kwargs): """Return pseudo-density array.""" method = kwargs.pop('method', 'dipole') self.initialize_density(method) return GPAW.get_pseudo_density(self, **kwargs) def get_all_electron_density(self, **kwargs): """Return all electron density array.""" method = kwargs.pop('method', 'dipole') self.initialize_density(method) return GPAW.get_all_electron_density(self, **kwargs)
if not io_only: R=0.7 # approx. experimental bond length a = 3.0 c = 4.0 H2 = Atoms([Atom('H', (a / 2, a / 2, (c - R) / 2)), Atom('H', (a / 2, a / 2, (c + R) / 2))], cell=(a, a, c)) calc = GPAW(xc='PBE', nbands=3, spinpol=False, txt=txt) H2.set_calculator(calc) H2.get_potential_energy() xc='LDA' # without spin lr = LrTDDFT(calc, xc=xc) lr.diagonalize() t1 = lr[0] # course grids for finegrid in [1,0]: lr = LrTDDFT(calc, xc=xc, finegrid=finegrid) lr.diagonalize() t3 = lr[0] print 'finegrid, t1, t3=', finegrid, t1 ,t3 equal(t1.get_energy(), t3.get_energy(), 5.e-4) # with spin lr_vspin = LrTDDFT(calc, xc=xc, nspins=2) singlet, triplet = lr_vspin.singlets_triplets() lr_vspin.diagonalize()
if setup_paths[0] != '.': setup_paths.insert(0, '.') gen('Mg', xcname='PBE', scalarrel=True, exx=True, yukawa_gamma=0.38) c = {'energy': 0.05, 'eigenstates': 3, 'density': 3} na2 = Cluster(Atoms('Mg', positions=[[0, 0, 0]])) na2.minimal_box(2.5, h=h) calc = GPAW(txt='mg_ivo.txt', xc='LCY-PBE:omega=0.38:excitation=singlet', eigensolver=RMMDIIS(), h=h, occupations=FermiDirac(width=0.0), spinpol=False, convergence=c) na2.set_calculator(calc) na2.get_potential_energy() (eps_homo, eps_lumo) = calc.get_homo_lumo() e_ex = eps_lumo - eps_homo equal(e_singlet, e_ex, 0.15) calc.write('mg.gpw') c2 = GPAW('mg.gpw') assert c2.hamiltonian.xc.excitation == 'singlet' lr = LrTDDFT(calc, txt='LCY_TDDFT_Mg.log', istart=4, jend=5, nspins=2) lr.write('LCY_TDDFT_Mg.ex.gz') if world.rank == 0: lr2 = LrTDDFT('LCY_TDDFT_Mg.ex.gz') lr2.diagonalize() ex_lr = lr2[1].get_energy() * Hartree equal(e_singlet_lr, ex_lr, 0.15)
H2 = Atoms([ Atom('H', (a / 2, a / 2, (c - R) / 2)), Atom('H', (a / 2, a / 2, (c + R) / 2)) ], cell=(a, a, c)) calc = GPAW(xc=xc, nbands=2, spinpol=False, eigensolver='rmm-diis', txt=txt) H2.set_calculator(calc) H2.get_potential_energy() calc.write('H2saved_wfs.gpw', 'all') calc.write('H2saved.gpw') wfs_error = calc.wfs.eigensolver.error #print "-> starting directly after a gs calculation" lr = LrTDDFT(calc, txt='-') lr.diagonalize() #print "-> reading gs with wfs" gs = GPAW('H2saved_wfs.gpw', txt=txt) # check that the wfs error is read correctly, # but take rounding errors into account assert (abs(calc.wfs.eigensolver.error / gs.wfs.eigensolver.error - 1) < 1e-8) lr1 = LrTDDFT(gs, xc=xc, txt='-') lr1.diagonalize() # check the oscillator strrength assert (abs(lr1[0].get_oscillator_strength()[0] / lr[0].get_oscillator_strength()[0] - 1) < 1e-10) #print "-> reading gs without wfs" gs = GPAW('H2saved.gpw', txt=None)
H2.set_calculator(calc) H2.get_potential_energy() ## calc.write('H2.gpw', 'all') else: calc = GPAW('H2.gpw', txt=txt) #calc.initialize_wave_functions() #----------------------------------------------------------- # DFT only xc = 'LDA' # no spin lr = LrTDDFT(calc, xc=xc) lr.diagonalize() lr_ApmB = LrTDDFT(calc, xc=xc, force_ApmB=True) lr_ApmB.diagonalize() parprint('lr=', lr) parprint('ApmB=', lr_ApmB) equal(lr[0].get_energy(), lr_ApmB[0].get_energy(), 5.e-10) # with spin parprint('------ with spin') if not load: c_spin = GPAW(xc='PBE', nbands=2, spinpol=True, parallel={'domain': mpi.world.size},
H2.set_calculator(calc) H2.get_potential_energy() ## calc.write('H2.gpw', 'all') else: calc = GPAW('H2.gpw', txt=txt) #calc.initialize_wave_functions() #----------------------------------------------------------- # DFT only xc='LDA' # no spin lr = LrTDDFT(calc, xc=xc) lr.diagonalize() lr_ApmB = LrTDDFT(calc, xc=xc, force_ApmB=True) lr_ApmB.diagonalize() print 'lr=', lr print 'ApmB=', lr_ApmB equal(lr[0].get_energy(), lr_ApmB[0].get_energy(), 5.e-10) # with spin print '------ with spin' if not load: c_spin = GPAW(xc='PBE', nbands=2, spinpol=True, parallel={'domain': mpi.world.size}, txt=txt) H2.set_calculator(c_spin)
# GPAW from gpaw import GPAW from gpaw.lrtddft import LrTDDFT from gpaw.lrtddft import photoabsorption_spectrum print( f'------------ Extracting shortened photoabsorption spectrum ------------' ) start = time.time() # Import LrTDDFT results from Task 1 lr = LrTDDFT('../task1/TDDFT_Task1.dat') lr.diagonalize(energy_range=4) # Only include up to 4 eV # Generate spectrum and save it wd = 0.06 photoabsorption_spectrum(lr, f'spectrum_w{wd}.dat', width=wd) # Extract all information about all transitions print('** LrTDDFT.analyse() output **') lr.analyse() print('*******************************') end = time.time() print('-------- Photoabsorption spectrum extracted in: ' + f'{(end-start):.2f} s --------'.rjust(34)) print('----------------------------------------------------------------------')