Exemple #1
0
db = sql.SQLiteDB('calc.db', table='calc')
idx_lst = db.get_list1d("select idx from calc")

cols = [
    ('etot', 'float'),  # eV
    ('pressure', 'float'),  # GPa
    ('volume', 'float'),  # Ang**3
    ('forces_rms', 'float'),  # eV / Ang
    ('sxx', 'float'),  # GPa
    ('syy', 'float'),  # GPa
    ('szz', 'float'),  # GPa
]
db.add_columns(cols)

for idx in idx_lst:
    print(idx)
    struct = io.cpickle_load('results/%i/traj.pk' % idx)[-1]
    db.execute("update calc set etot=? where idx==?", (struct.etot, idx))
    db.execute("update calc set volume=? where idx==?", (struct.volume, idx))
    db.execute("update calc set pressure=? where idx==?",
               (struct.pressure, idx))
    db.execute("update calc set sxx=? where idx==?",
               (struct.stress[0, 0], idx))
    db.execute("update calc set syy=? where idx==?",
               (struct.stress[1, 1], idx))
    db.execute("update calc set szz=? where idx==?",
               (struct.stress[2, 2], idx))
    db.execute("update calc set forces_rms=? where idx==?",
               (num.rms(struct.forces), idx))
db.commit()
Exemple #2
0
# Load parsed results and put some values in the database.

from pwtools import sql, io, num

db = sql.SQLiteDB('calc.db', table='calc')
idx_lst = db.get_list1d("select idx from calc")

cols = [('etot', 'float'),          # eV
        ('pressure', 'float'),      # GPa
        ('volume', 'float'),        # Ang**3
        ('forces_rms', 'float'),    # eV / Ang
        ('sxx', 'float'),           # GPa
        ('syy', 'float'),           # GPa
        ('szz', 'float'),           # GPa
        ]
db.add_columns(cols)

for idx in idx_lst:
    print idx
    struct = io.cpickle_load('results/%i/traj.pk' %idx)[-1]
    db.execute("update calc set etot=? where idx==?", (struct.etot, idx))
    db.execute("update calc set volume=? where idx==?", (struct.volume, idx))
    db.execute("update calc set pressure=? where idx==?", (struct.pressure, idx))
    db.execute("update calc set sxx=? where idx==?", (struct.stress[0,0], idx))
    db.execute("update calc set syy=? where idx==?", (struct.stress[1,1], idx))
    db.execute("update calc set szz=? where idx==?", (struct.stress[2,2], idx))
    db.execute("update calc set forces_rms=? where idx==?",
               (num.rms(struct.forces), idx))
db.commit()
Exemple #3
0
    def __init__(self,
                 freq,
                 dos,
                 temp=None,
                 skipfreq=False,
                 eps=1.5 * num.EPS,
                 fixnan=False,
                 nanfill=0.0,
                 dosarea=None,
                 integrator=trapz,
                 verbose=True):
        """                 
        Parameters
        ----------
        freq : 1d array
            frequency f (NOT 2*pi*f) [cm^-1]
        dos : 1d array
            phonon dos such that int(freq) dos = 3*natom
        temp : 1d array, optional
            temperature range [K], if not given in the constructor then use
            `temp` in the calculation methods
        skipfreq : bool, optional
            Ignore frequencies and DOS values where the frequencies are
            negative or close to zero, i.e. all DOS curve values where `freq` <
            `eps`. The number and rms of the skipped values is printed if
            `verbose=True`.
        eps : float, optional
            Threshold for `skipfreq`. Default is ~1.5*2.2e-16 . 
        fixnan : bool, optional
            Use if YKWYAD, test before using! Currently, set all NaNs occuring
            during integration to `nanfill`. This is a HACK b/c we must assume
            that these numbers should be `nanfill`.
        nanfill : float, optional
            During integration over temperature, set NaNs to this value.
        dosarea : float or None
            If not None, then re-normalize the area int(freq) dos to `dosarea`,
            after `skipfreq` was applied if used.
        integrator : callable
            Function which integrates x-y data. Called as ``integrator(y,x)``,
            like ``scipy.integrate.{trapz,simps}``. Usually, `trapz` is
            numerically more stable for weird DOS data and accurate enough if
            the freqeuency axis resolution is good.
        verbose : bool, optional
            Print warnings. Recommended for testing.

        Notes
        -----
        `skipfreq` and `fixnan`: Sometimes, a few frequencies (ususally the 1st
        few values only) are close to zero and negative, and the DOS is very
        small there. `skipfreq` can be used to ignore this region. The default
        is False b/c it may hide large negative frequencies (i.e. unstable
        structure), which is a perfectly valid result (but you shouldn't do
        thermodynamics with that :) Even if there are no negative frequencies,
        you can have frequencies (usually the first) beeing exactly zero or
        close to that (order 1e-17). That can cause numerical problems (NaNs)
        in some calculations so we may skip them and their DOS values, which
        must be assumed to be small. If you still encounter NaNs during
        integration, you may use `fixnan` to set them to `nanfill`. But that is a
        hack. If you cannot get rid of NaNs by `skipfreq`, then your freq-dos
        data is probably fishy!
        """
        # Notes
        # -----
        # - This is actually a re-implementation of F_QHA.f90 found in Quantum
        #   Espresso as of v4.2.
        # - All relations can be found in M.T. Dove, Introduction to Lattice
        #   Dynamics, ch. 5 .
        # - The frequency axis "f" in cm^-1 is what QE's matdyn.x returns
        #   when it calculates the phonon DOS (input: dos=.true.).
        # - For high T, Cv in units of R, the universal gas constant, should
        #   approach 3*N where N = natom = atoms in the unit cell. This is the
        #   Dulong-Petit limit (usually 3*N*R, here 3*N).
        #
        # Theory (example Cv):
        # --------------------
        #
        # Let Z = hbar*w/(2*kb*T), D(w) = phonon dos.
        # Cv(T) = kb * Z**2 * Int(w) [w**2 * D(w) / sinh(z))**2]
        #
        # Cv is in J/K. To get Cv in R[J/(mol*K)], one would have to do
        #   Cv[J/K] * Navo[1/mol] / R = Cv[J/K] / kb[J/K]
        # since kb = R/Navo, with
        #   R = gas constant = 8.314 J/(mol*K)
        #   Navo = Avogadro's number = 6e23
        #
        # So, Cv [R] == Cv [kb]. The same holds for the entropy Svib.
        #
        # We save the division by "kb" by dropping the "kb" prefactor:
        #   Cv(T) = Z**2 * Int(w) [w**2 * D(w) / sinh(z))**2]
        #          ^^^^
        # random note:
        #
        # in F_QHA.f90:
        #   a3 = 1.0/8065.5/8.617e-5 # = hbar*c0*100*2*pi / kb
        #   Did you know that?
        #
        # All formulas (cv, fvib etc) are written for angular frequency
        # w=2*pi*freq. Either we use hbar*w or h*freq. We do the latter.
        # We also convert s -> cm and keep freq in [cm^-1].
        #
        # cm^-1 -> 1/s       : * c0*100
        # 1/s   -> cm^-1     : / (c0*100)
        # s     -> cm        : * c0*100
        # => hbar or h: J*s -> J*cm : *c0*100
        self.f = freq
        self.dos = dos
        self.T = temp
        self.h = hplanck * c0 * 100
        self.kb = kb
        self.fixnan = fixnan
        self.skipfreq = skipfreq
        self.verbose = verbose
        self.eps = eps
        self.nanfill = nanfill
        self.dosarea = dosarea
        self.integrator = integrator

        assert len(self.f) == len(self.dos), ("freq and dos don't have "
                                              "equal length")
        if self.verbose:
            print("HarmonicThermo: number of dos points: %i" % len(self.f))

        if self.skipfreq:
            mask = self.f > self.eps
            if self.verbose:
                imask = np.invert(mask)
                nskip = len(imask.nonzero()[0])
                if len(imask) > 0:
                    frms = num.rms(self.f[imask])
                    drms = num.rms(self.dos[imask])
                    self._printwarn("HarmonicThermo: skipping %i dos points: "
                                    "rms(f)=%e, rms(dos)=%e" %
                                    (nskip, frms, drms))
            self.f = self.f[mask]
            self.dos = self.dos[mask]

        if self.dosarea is not None:
            self.dos = self._norm_int(self.dos,
                                      self.f,
                                      area=float(self.dosarea))
Exemple #4
0
    def __init__(self, freq, dos, temp=None, skipfreq=False, 
                 eps=1.5*num.EPS, fixnan=False, nanfill=0.0,
                 dosarea=None, integrator=trapz, verbose=True):
        """                 
        Parameters
        ----------
        freq : 1d array
            frequency f (NOT 2*pi*f) [cm^-1]
        dos : 1d array
            phonon dos such that int(freq) dos = 3*natom
        temp : 1d array, optional
            temperature range [K], if not given in the constructor then use
            `temp` in the calculation methods
        skipfreq : bool, optional
            Ignore frequencies and DOS values where the frequencies are
            negative or close to zero, i.e. all DOS curve values where `freq` <
            `eps`. The number and rms of the skipped values is printed if
            `verbose=True`.
        eps : float, optional
            Threshold for `skipfreq`. Default is ~1.5*2.2e-16 . 
        fixnan : bool, optional
            Use if YKWYAD, test before using! Currently, set all NaNs occuring
            during integration to `nanfill`. This is a HACK b/c we must assume
            that these numbers should be `nanfill`.
        nanfill : float, optional
            During integration over temperature, set NaNs to this value.
        dosarea : float or None
            If not None, then re-normalize the area int(freq) dos to `dosarea`,
            after `skipfreq` was applied if used.
        integrator : callable
            Function which integrates x-y data. Called as ``integrator(y,x)``,
            like ``scipy.integrate.{trapz,simps}``. Usually, `trapz` is
            numerically more stable for weird DOS data and accurate enough if
            the freqeuency axis resolution is good.
        verbose : bool, optional
            Print warnings. Recommended for testing.

        Notes
        -----
        `skipfreq` and `fixnan`: Sometimes, a few frequencies (ususally the 1st
        few values only) are close to zero and negative, and the DOS is very
        small there. `skipfreq` can be used to ignore this region. The default
        is False b/c it may hide large negative frequencies (i.e. unstable
        structure), which is a perfectly valid result (but you shouldn't do
        thermodynamics with that :) Even if there are no negative frequencies,
        you can have frequencies (usually the first) beeing exactly zero or
        close to that (order 1e-17). That can cause numerical problems (NaNs)
        in some calculations so we may skip them and their DOS values, which
        must be assumed to be small. If you still encounter NaNs during
        integration, you may use `fixnan` to set them to `nanfill`. But that is a
        hack. If you cannot get rid of NaNs by `skipfreq`, then your freq-dos
        data is probably fishy!
        """
        # Notes
        # -----
        # - This is actually a re-implementation of F_QHA.f90 found in Quantum
        #   Espresso as of v4.2.
        # - All relations can be found in M.T. Dove, Introduction to Lattice
        #   Dynamics, ch. 5 .
        # - The frequency axis "f" in cm^-1 is what QE's matdyn.x returns
        #   when it calculates the phonon DOS (input: dos=.true.).
        # - For high T, Cv in units of R, the universal gas constant, should
        #   approach 3*N where N = natom = atoms in the unit cell. This is the
        #   Dulong-Petit limit (usually 3*N*R, here 3*N).
        #
        # Theory (example Cv):
        # --------------------
        #
        # Let Z = hbar*w/(2*kb*T), D(w) = phonon dos.
        # Cv(T) = kb * Z**2 * Int(w) [w**2 * D(w) / sinh(z))**2]
        #
        # Cv is in J/K. To get Cv in R[J/(mol*K)], one would have to do 
        #   Cv[J/K] * Navo[1/mol] / R = Cv[J/K] / kb[J/K]
        # since kb = R/Navo, with 
        #   R = gas constant = 8.314 J/(mol*K)
        #   Navo = Avogadro's number = 6e23
        # 
        # So, Cv [R] == Cv [kb]. The same holds for the entropy Svib.
        #
        # We save the division by "kb" by dropping the "kb" prefactor:
        #   Cv(T) = Z**2 * Int(w) [w**2 * D(w) / sinh(z))**2]
        #          ^^^^
        # random note:
        #
        # in F_QHA.f90:
        #   a3 = 1.0/8065.5/8.617e-5 # = hbar*c0*100*2*pi / kb
        #   Did you know that?
        #
        # All formulas (cv, fvib etc) are written for angular frequency
        # w=2*pi*freq. Either we use hbar*w or h*freq. We do the latter.
        # We also convert s -> cm and keep freq in [cm^-1].
        #
        # cm^-1 -> 1/s       : * c0*100
        # 1/s   -> cm^-1     : / (c0*100)
        # s     -> cm        : * c0*100
        # => hbar or h: J*s -> J*cm : *c0*100
        self.f = freq
        self.dos = dos
        self.T = temp
        self.h = hplanck * c0 * 100
        self.kb = kb
        self.fixnan = fixnan
        self.skipfreq = skipfreq
        self.verbose = verbose
        self.eps = eps
        self.nanfill = nanfill
        self.dosarea = dosarea
        self.integrator = integrator
        
        assert len(self.f) == len(self.dos), ("freq and dos don't have "
                                             "equal length")
        if self.verbose:
            print "HarmonicThermo: number of dos points: %i" %len(self.f)
        
        if self.skipfreq:
            mask = self.f > self.eps
            if self.verbose:
                imask = np.invert(mask)
                nskip = len(imask.nonzero()[0])
                if len(imask) > 0:
                    frms = num.rms(self.f[imask])
                    drms = num.rms(self.dos[imask])
                    self._printwarn("HarmonicThermo: skipping %i dos points: "
                        "rms(f)=%e, rms(dos)=%e" %(nskip, frms, drms))
            self.f = self.f[mask]
            self.dos = self.dos[mask]
        
        if self.dosarea is not None:
            self.dos = self._norm_int(self.dos, self.f, area=float(self.dosarea))