def __init__( self, folding=None, width=0.08, # Gauss/Lorentz width ): self.folding = folding Folder.__init__(self, width, folding)
def __init__(self, folding=None, width=0.08): """Evaluate the polarizability from sum over states. Parameters ---------- folding : string or None(default) Name of the folding function, see gpaw/folder.py for options. None means do not fold at all. width : float The width to be transferred to the folding function. """ self.folding = folding if folding is not None: Folder.__init__(self, width, folding)
def rotatory_spectrum(exlist=None, filename=None, emin=None, emax=None, de=None, energyunit='eV', folding='Gauss', width=0.08, # Gauss/Lorentz width comment=None ): """Write out a folded rotatory spectrum. See spectrum() for explanation of the parameters. """ # output out = sys.stdout if filename is not None: out = open(filename, 'w') if comment: print('#', comment, file=out) print('# Rotatory spectrum from linear response TD-DFT', file=out) print('# GPAW version:', version, file=out) if folding is not None: # fold the spectrum print('# %s folded, width=%g [%s]' % (folding, width, energyunit), file=out) print('# om [%s] R [cgs]' % energyunit, file=out) x = [] y = [] for ex in exlist: x.append(ex.get_energy() * Hartree) y.append(ex.get_rotatory_strength()) if energyunit == 'nm': # transform to experimentally used wavelength [nm] x = 1.e+9 * 2 * np.pi * _hbar * _c / _e / np.array(x) y = np.array(y) elif energyunit != 'eV': raise RuntimeError('currently only eV and nm are supported') energies, values = Folder(width, folding).fold(x, y, de, emin, emax) for e, val in zip(energies, values): print('%10.5f %12.7e' % (e, val), file=out) if filename is not None: out.close()
def set_folding(self, folding, width): BaseInducedField.set_folding(self, folding, width) if self.folding is None: self.folder = Folder(None, None) else: if self.folding == 'Gauss': self.folder = Folder(self.width, 'ComplexGauss') elif self.folding == 'Lorentz': self.folder = Folder(self.width, 'ComplexLorentz') else: raise RuntimeError('unknown folding "' + self.folding + '"')
def get_folded_spectrum( exlist=None, emin=None, emax=None, de=None, energyunit='eV', folding='Gauss', width=0.08, # Gauss/Lorentz width form='r'): """Return folded spectrum.""" x = [] y = [] for ex in exlist: x.append(ex.get_energy() * Hartree) y.append(ex.get_oscillator_strength(form)) if energyunit == 'nm': # transform to experimentally used wavelength [nm] x = 1.e+9 * 2 * np.pi * _hbar * _c / _e / np.array(x) elif energyunit != 'eV': raise RuntimeError('currently only eV and nm are supported') return Folder(width, folding).fold(x, y, de, emin, emax)
from gpaw.test import equal from gpaw.utilities.folder import Folder, Lorentz, Voigt # noqa # Gauss and Lorentz functions width = 0.5 x = 1.5 equal(Gauss(width).get(x), exp(- x**2 / 2 / width**2) / sqrt(2 * pi) / width, 1.e-15) equal(Gauss(width).fwhm, width * np.sqrt(8 * np.log(2)), 1.e-15) equal(Lorentz(width).get(x), width / (x**2 + width**2) / pi, 1.e-15) equal(Lorentz(width).fwhm, width * 2, 1.e-15) # folder function for func in [Gauss, Lorentz, Voigt]: folder = Folder(width, func(width).__class__.__name__) x = [0, 2] y = [[2, 0, 1], [1, 1, 1]] xl, yl = folder.fold(x, y, dx=.7) # check first value yy = np.dot(np.array(y)[:, 0], func(width).get(xl[0] - np.array(x))) equal(yl[0, 0], yy, 1.e-15)
class LrTDDFTInducedField(BaseInducedField): """Induced field class for linear response TDDFT. Attributes (see also ``BaseInducedField``): ------------------------------------------- lr: LrTDDFT object LrTDDFT object """ def __init__(self, filename=None, paw=None, lr=None, ws='all', frequencies=None, folding='Gauss', width=0.08, kickdir=0 ): """ Parameters (see also ``BaseInducedField``): ------------------------------------------- paw: GPAW object GPAW object for ground state lr: LrTDDFT object LrTDDFT object kickdir: int Kick direction: 0, 1, 2 for x, y, z """ # TODO: change kickdir to general kick = [1e-3, 1-e3, 0] etc. if type(lr) is not LrTDDFT: raise RuntimeError('Provide LrTDDFT object.') # Check that lr is diagonalized if len(lr) == 0: raise RuntimeError('Diagonalize LrTDDFT first.') self.lr = lr # "Kick" direction self.kickdir = kickdir self.readwritemode_str_to_list = \ {'': ['Frho', 'atoms'], 'all': ['Frho', 'Fphi', 'Fef', 'Ffe', 'atoms'], 'field': ['Frho', 'Fphi', 'Fef', 'Ffe', 'atoms']} BaseInducedField.__init__(self, filename, paw, ws, frequencies, folding, width) def initialize(self, paw, allocate=True): BaseInducedField.initialize(self, paw, allocate) # Artificial background electric field (linear response) # TODO: change kickdir to general kick = [1e-3, 1-e3, 0] etc. Fbgef_v = np.zeros((self.nv,), dtype=float) Fbgef_v[self.kickdir] = 1.0 self.Fbgef_v = Fbgef_v # Initialize PAW object self.density.ghat.set_positions(self.atoms.get_scaled_positions()) paw.converge_wave_functions() def set_folding(self, folding, width): BaseInducedField.set_folding(self, folding, width) if self.folding is None: self.folder = Folder(None, None) else: if self.folding == 'Gauss': self.folder = Folder(self.width, 'ComplexGauss') elif self.folding == 'Lorentz': self.folder = Folder(self.width, 'ComplexLorentz') else: raise RuntimeError('unknown folding "' + self.folding + '"') def get_induced_density(self, from_density='comp', gridrefinement=2): paw = self.paw lr = self.lr omega_w = self.omega_w if gridrefinement == 1: gd = self.gd elif gridrefinement == 2: gd = self.density.finegd else: raise NotImplementedError nkss = len(lr.kss) nexcs = len(lr) omega_I = np.empty((nexcs), dtype=float) # C_Iij: weights for each excitation I and KS-pair ij C_Iij = np.zeros((nexcs, nkss), dtype=float) # Calculate C_Iij FIsqfe_ij = np.zeros((nkss), dtype=float) for I, exc in enumerate(lr): omega_I[I] = exc.energy B = 0.0 for ij, ks in enumerate(lr.kss): FIsqfe_ij[ij] = exc.f[ij] * np.sqrt(ks.fij * ks.energy) B += ks.mur[self.kickdir] * FIsqfe_ij[ij] C_Iij[I] = 2 * B * FIsqfe_ij # Fold C_Iij to C_wij # C_wij: weights for each requested frequency w and KS-pair ij self.omega_w, C_wij = self.folder.fold_values(omega_I, C_Iij, omega_w) assert (self.omega_w == omega_w).all() # TODO: remove Fn_wg = gd.zeros((self.nw), dtype=complex) kpt_u = paw.wfs.kpt_u for ij, ks_ in enumerate(lr.kss): # TODO: better output of progress parprint('%d/%d' % (ij, nkss)) # TODO: speedup: # for each w, check magnitude of C_wij and # take C_wij for those ij that contribute most # Take copy so that memory for pair density is released # after each loop iteration ks = ks_.copy() # Initialize pair density kpt = kpt_u[ks.spin] ks.set_paw(paw) ks.initialize(kpt, ks.i, ks.j) # Get pair density # TODO: gridrefinements yes_finegrid = gridrefinement == 2 if from_density == 'pseudo': nij_g = ks.get(finegrid=yes_finegrid) elif from_density == 'comp': nij_g = ks.with_compensation_charges(finegrid=yes_finegrid) elif from_density == 'ae': nij_g = ks.with_ae_corrections(finegrid=yes_finegrid) # TODO: better to split pair density in pseudo density part # and FD_asp etc. coefficients (like in time-propagation). # Then do gridrefinement and add AE/comp corrections afterwards # -> speedup (no need to do summations on fine grid) # TODO: speedup: check magnitude of C_wij (see above) for w in range(self.nw): Fn_wg[w] += nij_g * C_wij[w, ij] # Return charge density (electrons = negative charge) return - Fn_wg, gd
def __init__(self, folding=None, width=0.08, # Gauss/Lorentz width ): self.folding = folding Folder.__init__(self, width, folding)
def spectrum( exlist=None, filename=None, emin=None, emax=None, de=None, energyunit='eV', folding='Gauss', width=0.08, # Gauss/Lorentz width comment=None): """Write out a folded spectrum. Parameters: =============== =================================================== ``exlist`` ExcitationList ``filename`` File name for the output file, STDOUT if not given ``emin`` min. energy, set to cover all energies if not given ``emax`` max. energy, set to cover all energies if not given ``de`` energy spacing ``energyunit`` Energy unit 'eV' or 'nm', default 'eV' ``folding`` Gauss (default) or Lorentz ``width`` folding width in terms of the chosen energyunit =============== =================================================== all energies in [eV] """ # output out = sys.stdout if filename != None: out = open(filename, 'w') if comment: print >> out, '#', comment print >> out, '# Photoabsorption spectrum from linear response TD-DFT' print >> out, '# GPAW version:', version if folding is not None: # fold the spectrum print >> out, '# %s folded, width=%g [%s]' % (folding, width, energyunit) print >> out,\ '# om [%s] osz osz x osz y osz z'\ % energyunit x = [] y = [] for ex in exlist: x.append(ex.get_energy() * Hartree) y.append(ex.get_oscillator_strength()) if energyunit == 'nm': # transform to experimentally used wavelength [nm] x = 1.e+9 * 2 * np.pi * _hbar * _c / _e / np.array(x) y = np.array(y) elif energyunit != 'eV': raise RuntimeError('currently only eV and nm are supported') energies, values = Folder(width, folding).fold(x, y, de, emin, emax) for e, val in zip(energies, values): print >> out, "%10.5f %12.7e %12.7e %11.7e %11.7e" % \ (e,val[0],val[1],val[2],val[3]) if filename != None: out.close()
# Gauss and Lorentz functions width = 0.5 x = 1.5 equal(Gauss(width).get(x), exp(- x**2 / 2 / width**2) / sqrt(2 * pi) / width, 1.e-15) equal(Lorentz(width).get(x), width / (x**2 + width**2) / pi, 1.e-15) # folder function for name in ['Gauss', 'Lorentz']: folder = Folder(width, name) x = [0, 2] y = [[2, 0, 1], [1, 1, 1]] xl, yl = folder.fold(x, y, dx=.7) # check first value if name == 'Lorentz': func = Lorentz(width) else: func = Gauss(width) yy = np.dot(np.array(y)[:, 0], func.get(xl[0] - np.array(x))) equal(yl[0, 0], yy, 1.e-15) # write spectrum
plt.axis([-1000, 6000, 0, 1.05]) plt.ylabel('HR factors [a.u.]') plt.xlabel('frequency [cm-1]') plt.show() #Plot Franck-Condon factors FC, f = a.get_Franck_Condon_factors(n, T, F) for l in range(len(FC)): plt.vlines(f[l], 0, FC[l], color=colors[l], label=labels[l], linewidth=2.0) #Fold the spectrum with a gaussian function width = 300 folding = 'Gauss' x = [j for j in chain(*f)] y = [j for j in chain(*FC)] X, Y = Folder(width, folding).fold(x, y) plt.plot(X, Y * 750, color='black', linewidth=2.0, label='Temperature=' + str(T) + 'K, #quanta=' + str(n) + ', width of gaussian=' + str(width) + 'cm^-1', linestyle='dashed') plt.legend(loc='upper right') plt.axis([-1000, 6000, 0, 0.6]) plt.ylabel('FC factors [a.u.]') plt.xlabel('frequency [cm-1]') plt.show()
def dielectric( exlist, volume, filename=None, emin=None, emax=None, de=None, energyunit='eV', width=0.08, # width in energyunit comment=None, form='v'): """Write out the dielectric function Parameters: =============== =================================================== ``exlist`` ExcitationList ``volume`` Unit cell volume in Angstrom**3 ``filename`` File name for the output file, STDOUT if not given ``emin`` min. energy, set to cover all energies if not given ``emax`` max. energy, set to cover all energies if not given ``de`` energy spacing ``energyunit`` Energy unit 'eV' or 'nm', default 'eV' ``width`` folding width in terms of the chosen energyunit =============== =================================================== all energies in [eV] """ # output out = sys.stdout if filename is not None: out = open(filename, 'w') if comment: print('#', comment, file=out) print('# Dielec function', file=out) print('# GPAW version:', gpaw.__version__, file=out) print('# width={0} [{1}]'.format(width, energyunit), file=out) if form == 'r': print('# length form', file=out) else: assert (form == 'v') print('# velocity form', file=out) print( '# om [{0}] eps1/eps0 eps2/eps0 n k R'.format( energyunit), file=out) x = [] y = [] for ex in exlist: x.append(ex.get_energy() * Hartree) y.append(ex.get_oscillator_strength(form)) if energyunit != 'eV': raise RuntimeError('currently only eV is supported') pre = 4. * np.pi / volume * Bohr**3 * Hartree**2 energies, values = Folder(width, 'RealLorentzPole').fold(x, y, de, emin, emax) eps1 = 1 + pre * values.T[0] energies, values = Folder(width, 'ImaginaryLorentzPole').fold( x, y, de, emin, emax) eps2 = pre * values.T[0] N = np.sqrt(0.5 * (np.sqrt(eps1**2 + eps2**2) + eps1)) K = np.sqrt(0.5 * (np.sqrt(eps1**2 + eps2**2) - eps1)) R = ((N - 1)**2 + K**2) / ((N + 1)**2 + K**2) for e, e1, e2, n, k, r in zip(energies, eps1, eps2, N, K, R): print('%10.5f %12.7e %12.7e %12.7e %12.7e %12.7e' % (e, e1, e2, n, k, r), file=out) if filename is not None: out.close()