Пример #1
0
 def __init__(
         self,
         folding=None,
         width=0.08,  # Gauss/Lorentz width
 ):
     self.folding = folding
     Folder.__init__(self, width, folding)
Пример #2
0
    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)
Пример #3
0
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 + '"')
Пример #5
0
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)
Пример #6
0
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
Пример #8
0
 def __init__(self, folding=None, width=0.08, # Gauss/Lorentz width
              ):
     self.folding = folding
     Folder.__init__(self, width, folding)
Пример #9
0
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()
Пример #10
0
# 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
Пример #11
0
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()
Пример #12
0
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()