pes.save_folded_pes(filename=None, folding=None) # check for correct shift VDE = calc_plus.get_potential_energy() - calc.get_potential_energy() BE_HOMO = 1.e23 be_n, f_n = pes.get_energies_and_weights() for be, f in zip(be_n, f_n): if f > 0.1 and be < BE_HOMO: BE_HOMO = be equal(BE_HOMO, VDE) lr = LrTDDFT(calc_plus, xc=xc) out = 'lrpes.dat' pes = TDDFTPES(calc, lr) pes.save_folded_pes(filename=out, folding='Gauss') pes.save_folded_pes(filename=None, folding=None) energy_tolerance = 0.0001 niter_tolerance = 1 equal(e_H2, -3.90059, energy_tolerance) equal(e_H2_plus, 10.5659703, energy_tolerance) # io out = 'lrpes.dat.gz' lr.write(out) lr = LrTDDFT(out) lr.set_calculator(calc_plus) pes = TDDFTPES(calc, lr) pes.save_folded_pes(filename=None, folding=None)
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)
# check for correct shift VDE = calc_plus.get_potential_energy() - calc.get_potential_energy() BE_HOMO = 1.e23 be_n, f_n = pes.get_energies_and_weights() for be, f in zip(be_n, f_n): if f > 0.1 and be < BE_HOMO: BE_HOMO = be equal(BE_HOMO, VDE) lr = LrTDDFT(calc_plus, xc=xc) out = 'lrpes.dat' pes = TDDFTPES(calc, lr) pes.save_folded_pes(filename=out, folding='Gauss') pes.save_folded_pes(filename=None, folding=None) energy_tolerance = 0.0001 niter_tolerance = 1 equal(e_H2, -3.90059, energy_tolerance) equal(e_H2_plus, 10.5659703, energy_tolerance) # io out = 'lrpes.dat.gz' lr.write(out) lr = LrTDDFT(out) lr.set_calculator(calc_plus) pes = TDDFTPES(calc, lr) pes.save_folded_pes(filename=None, folding=None)