コード例 #1
0
ファイル: ddk.py プロジェクト: zbwang/abipy
    def get_doses(self, method="gaussian", step=0.1, width=0.2):
        """
        Compute the electronic DOS on a linear mesh.

        Args:
            method: String defining the method for the computation of the DOS.
            step: Energy step (eV) of the linear mesh.
            width: Standard deviation (eV) of the gaussian.

        Returns: |ElectronDos| object.
        """
        self.kpoints.check_weights()
        edos = self.ddks[0].ebands.get_edos(method=method, step=step, width=width)
        values = np.zeros((self.nsppol, nw))
        mesh = edos[0].mesh
        #vmod_skb = self.vskb
        if method == "gaussian":
            for spin in range(self.nsppol):
                for k, kpoint in enumerate(self.kpoints):
                    wk = kpoint.weight
                    for band in range(self.nband):
                        e = self.eigens[spin, k, band]
                        values[spin] += wk * vmod[spin, k, band] * gaussian(mesh, width, center=e)
        else:
            raise NotImplementedError("Method %s is not supported" % method)

        vdos_spin = [Function1D(mesh, values[spin]) for spin in range(self.nsppol)]
        vdos = 2 * Function1D(mesh, values[0]) if self.nsppol == 1 else vdos_spin[0] + vdos_spin[1]

        return dict2namedtuple(edos=edos, vdos=vdos, vdos_spin=vdos_spin)
コード例 #2
0
    def __init__(self, structure, qpoints, wmesh, emacros_q, info):
        """
        Args:
            structure: |Structure| object.
            qpoints: |KpointList| with the q-points in reduced coordinates.
            wmesh: Array-like object with the frequency mesh (eV).
            emacros_q: Iterable with the macroscopic dielectric function for the different q-points.
            info: Dictionary containing info on the calculation that produced
                  the results (read from file). It must contain the following keywords:

                    - "lfe": True if local field effects are included.
                    - "calc_type": string defining the calculation type.
        """
        self.wmesh = np.array(wmesh)
        self.qpoints = qpoints
        assert len(self.qpoints) == len(emacros_q)
        self.info = info

        self.emacros_q, em_avg = [], np.zeros(len(wmesh), dtype=complex)
        for emq in emacros_q:
            em_avg += emq
            self.emacros_q.append(Function1D(wmesh, emq))
        self.emacros_q = tuple(self.emacros_q)

        # Compute the average value.
        # TODO: One should take into account the star of q, but I need the symops
        self.emacro_avg = Function1D(wmesh, em_avg / self.num_qpoints)
コード例 #3
0
    def __init__(self, mesh, values):
        values = np.atleast_2d(values)
        self.nsppol = len(values)

        self.a2f_spin, a2f_tot = [], np.zeros(len(mesh))

        for vs in values:
            self.a2f_spin.append(Function1D(mesh, vs))
            a2f_tot += vs

        # Spin dependent and total a2F(w)
        self.a2f_spin = tuple(self.a2f_spin)
        self.a2f = Function1D(mesh, a2f_tot)
コード例 #4
0
ファイル: scr.py プロジェクト: Npikeulg/abipy
    def get_emacro_lf(self, qpoint=(0, 0, 0)):
        """
        Compute the macroscopic dielectric function *with* local field effects
        1/ em1_{0,0)(q=0, w).

        Return :class:`Function1D`
        """
        em1 = self.get_em1(qpoint=qpoint)
        emacro = 1 / em1.wggmat[:, 0, 0]
        return Function1D(em1.real_wpts, emacro[:em1.nrew])
コード例 #5
0
    def to_func1d(self, red_coords=True):
        """Return list of Function."""
        table = self.to_array(red_coords)
        all_funcs = []

        for i in np.arange(3):
            for j in np.arange(3):
                all_funcs.append(Function1D(self._wmesh, table[:, i, j]))

        return all_funcs
コード例 #6
0
    def read_emacro_lf(self, kpoint=(0, 0, 0)):
        """
        Read the macroscopic dielectric function *with* local field effects 1 / em1_{0,0)(kpoint, omega).

        Return: |Function1D| object.
        """
        if self.netcdf_name == "inverse_dielectric_function":
            em1 = self.read_wslice(kpoint, ig1=0, ig2=0)
            emacro = 1 / em1[:self.nrew]
        else:
            raise NotImplementedError("emacro_lf with netcdf != InverseDielectricFunction")

        return Function1D(np.real(self.wpoints[:self.nrew]).copy(), emacro)
コード例 #7
0
ファイル: scr.py プロジェクト: zbwang/abipy
    def read_eelf(self, kpoint=(0, 0, 0)):
        """
        Read electron energy loss function

            - Im(1/ emacro)

        Return: |Function1D| object.
        """
        # eelf = -Im(1 / eM)
        emacro_lf = self.read_emacro_lf(kpoint=kpoint)
        #emacro_lf = self.read_emacro_nlf(kpoint=kpoint)
        values = (-1 / emacro_lf.values).imag

        return Function1D(emacro_lf.mesh.copy(), values)
コード例 #8
0
ファイル: phonons.py プロジェクト: gmrigna/abipy
    def get_harmonic_thermo(self, tstart, tstop, num=50):
        """
        Compute thermodinamic properties from the phonon DOS within the harmonic approximation.

        tstart: The starting value (in Kelvin) of the temperature mesh. 
        tstop: The end value (in Kelvin) of the mesh.
        num: int, optional Number of samples to generate. Default is 50.
        """
        tmesh = np.linspace(tstart, tstop, num=num)

        coth = lambda x: 1.0 / np.tanh(x)
        csch2 = lambda x: 1.0 / (np.sinh(x)**2)

        # Boltzmann constant in Ha/K
        kb_HaK = 8.617343e-5 / Ha_to_eV

        for i, gw in enumerate(self.values):
            if gw > 0: break
        #i = self.dos.find_mesh_index(0.0)

        # Use atomic units
        w = self.mesh[i:] * eV_to_Ha
        gw = self.values[i:] * Ha_to_eV

        from scipy.integrate import cumtrapz

        def integrate(values):
            return cumtrapz(values, x=w)[-1]

        #w, gw = w[i:], gw[i:]
        # TODO
        # Check for possible numerical instabilities when w ~ 0 or negative
        # Prefactors are missing!
        df, de, cv, s = map(np.empty, 4 * (len(tmesh), ))
        for i, temp in enumerate(tmesh):
            # Equations in Xavier's paper.
            kt = kb_HaK * temp
            wd2kt = w / (2 * kt)
            df[i] = kt * integrate(np.log(2 * np.sinh(wd2kt)) * gw)
            de[i] = integrate(w * coth(wd2kt) * gw)
            cv[i] = integrate(wd2kt * wd2kt * csch2(wd2kt) * gw)
            s[i] = integrate(
                (wd2kt * coth(wd2kt) - np.log(2 * np.sinh(wd2kt))) * gw)

        locvars = locals()
        return HarmonicThermo(
            **{
                name: Function1D(tmesh, locvars[name])
                for name in ("df", "de", "cv", "s")
            })
コード例 #9
0
ファイル: scr.py プロジェクト: Npikeulg/abipy
    def get_emacro_nlf(self, qpoint=(0, 0, 0)):
        """
        Compute the macroscopic dielectric function *without* local field effects.
        e_{0,0)(q=0, w).

        Return :class:`Function1D`

        .. warning:
            This function performs the inversion of e-1 to get e.
            that can be quite expensive and memory demanding for large matrices!
        """
        em1 = self.get_em1(qpoint=qpoint)
        e = np.linalg.inv(em1.wggmat[:em1.nrew, :, :])

        return Function1D(em1.real_wpts, e[:, 0, 0])
コード例 #10
0
    def read_emacro_nlf(self, kpoint=(0, 0, 0)):
        """
        Read the macroscopic dielectric function *without* local field effects e_{0,0)(kpoint, omega).

        Return: |Function1D|

        .. warning::

            This function performs the inversion of e-1 to get e.
            that can be quite expensive and memory demanding for large matrices!
        """
        if self.netcdf_name == "inverse_dielectric_function":
            em1 = self.read_wggmat(kpoint)
            e = np.linalg.inv(em1.wggmat[:self.nrew, :, :])
        else:
            raise NotImplementedError("emacro_nlf with netcdf != InverseDielectricFunction")

        return Function1D(np.real(self.wpoints[:self.nrew]).copy(), e[:, 0, 0])
コード例 #11
0
    def get_thermal_expansion_coeff(self, tstart=0, tstop=800, num=100):
        """
        Calculates the thermal expansion coefficient as a function of temperature, using
        finite difference on the fitted values of the volume as a function of temperature.

        Args:
            tstart: The starting value (in Kelvin) of the temperature mesh.
            tstop: The end value (in Kelvin) of the mesh.
            num: int, optional Number of samples to generate. Default is 100.

        Returns: |Function1D|
        """
        f = self.fit_energies(tstart, tstop, num)

        dt = f.temp[1] - f.temp[0]
        alpha = (f.min_vol[2:] - f.min_vol[:-2]) / (2 * dt) / f.min_vol[1:-1]

        return Function1D(f.temp[1:-1], alpha)
コード例 #12
0
ファイル: atom.py プロジェクト: rahul1126/pseudo_dojo
    def get_intr2j0(self, ecut, numq=3001):
        r"""
        Compute 4\pi\int[(\frac{\sin(2\pi q r)}{2\pi q r})(r^2 n(r))dr].
        """
        qmax = np.sqrt(ecut / 2) / np.pi
        qmesh = np.linspace(0, qmax, num=numq, endpoint=True)
        outs = np.empty(len(qmesh))

        # Treat q == 0. Note that rmesh[0] > 0
        f = 4 * np.pi * self.rmesh**2 * self.values
        outs[0] = cumtrapz(f, x=self.rmesh)[-1]

        for i, q in enumerate(qmesh[1:]):
            twopiqr = 2 * np.pi * q * self.rmesh
            f = 4 * np.pi * (np.sin(twopiqr) /
                             twopiqr) * self.rmesh**2 * self.values
            outs[i + 1] = cumtrapz(f, x=self.rmesh)[-1]

        from abipy.core.func1d import Function1D
        ecuts = 2 * np.pi**2 * qmesh**2
        return Function1D(ecuts, outs)
コード例 #13
0
ファイル: demo_func1d.py プロジェクト: akakcolin/abipy
#!/usr/bin/env python
import wx
import numpy as np

from abipy.core.func1d import Function1D
from abipy.gui.awx.func1dframe import Func1dPlotFrame

app = wx.App()
func1d = Function1D.from_func(np.sin, np.arange(1,100,1))
frame = Func1dPlotFrame(None, func1d)
frame.Show()
app.MainLoop()
コード例 #14
0
ファイル: gw.py プロジェクト: gmrigna/abipy
 def get_spfunc(self, spin, kpoint, band):
     wmesh, spf_values = self.reader.read_spfunc(spin, kpoint, band)
     return Function1D(wmesh, spf_values)
コード例 #15
0
ファイル: raman.py プロジェクト: vishankkumar/abipy
    def get_lorentz_intensity(self,
                              temp,
                              laser_freq,
                              width,
                              non_anal_dir=None,
                              min_freq=None,
                              max_freq=None,
                              num=1000,
                              relative=False,
                              units="eV",
                              pol_in=None,
                              pol_out=None):
        """
        Calculates the broadened Raman intensities in arbitrary units for frequencies in an interval. It is
        possible to use the susceptibilities from the transverse modes only or to specify one of the directions
        with non analytical contributions. By default it returns a 3x3 matrix where each component is a
        Function1D object with the Raman intensities with different incoming (the first index) and outgoing
        (the second index) polarization. These are along the components along the standard axes (e.g. "xx" or
        "yz" components). If pol_in and pol_out a single Function1D is returned corresponding to the selected
        polarizations.

        Args:
            temp: temperature in K.
            laser_freq: frequency of the incident laser. The units are determined the "units"
                argument.
            width: the width of the Lorentz distribution. The units are determined the "units"
                argument.
            non_anal_dir: index of the direction along which the non analytical contribution
                has been calculated. Corresponds to the indices in the non_anal_directions attribute.
            min_freq: minimum frequency considered. If None it will be given by the minimum
                frequency with non zero intensities minus 10 times the width of the distribution.
                If given the units are determined by the "units" argument.
            max_freq: maximum frequency considered. If None it will be given by the maximum
                frequency with non zero intensities plus 10 times the width of the distribution.
                If given the units are determined by the "units" argument.
            num: number of frequencies in the interval (min_freq, max_freq).
            relative: if True the intensities will be rescaled so that the largest value is 1.
            units: the units in which the input and the output frequencies will be given.
                Possible values in ("eV", "meV", "Ha", "cm-1", "Thz")
            pol_in: the polarization of the incoming photon. If not None can be either either a string
                with one of the cartesian components i.e. "x", "y", "z" or an array with 3 elements
                representing the polarization direction. If not None pol_out can not be None.
            pol_out: the polarization of the outgoing photon. If not None can be either either a string
                with one of the cartesian components i.e. "x", "y", "z" or an array with 3 elements
                representing the polarization direction. If not None pol_in can not be None.

        Returns:
            If pol_in==pol_out==None a 3x3 list with a Function1D corresponding to the different
            components of the intensities. Otherwise a single Function1D with the  intensities of
            the selected polarizations. Each Function1D has "num" points.
        """

        i = self.get_modes_intensities(temp=temp,
                                       laser_freq=laser_freq,
                                       non_anal_dir=non_anal_dir,
                                       units=units,
                                       pol_in=pol_in,
                                       pol_out=pol_out)

        freqs, lorentz = self._get_lorentz_freqs_and_factor(
            intensity=i,
            non_anal_dir=non_anal_dir,
            min_freq=min_freq,
            max_freq=max_freq,
            num=num,
            width=width,
            units=units)

        # convert the frequencies to the desired units for the output
        x = freqs * abu.phfactor_ev2units(units)

        if pol_in is not None and pol_out is not None:
            li = np.dot(i, lorentz)
            if relative:
                li /= li.max()

            return Function1D(x, li)

        else:
            li = np.einsum("ij, ikl -> jkl", lorentz, i)

            li_func = [[None] * 3] * 3

            for i in range(3):
                for j in range(3):
                    y = li[:, i, j]
                    if relative:
                        y /= y.max()
                    li_func[i][j] = Function1D(x, y)

            return li_func
コード例 #16
0
ファイル: raman.py プロジェクト: vishankkumar/abipy
    def get_powder_lorentz_intensity(self,
                                     temp,
                                     laser_freq,
                                     width,
                                     non_anal_dir=None,
                                     min_freq=None,
                                     max_freq=None,
                                     num=1000,
                                     relative=False,
                                     units="eV"):
        """
        Calculates the broadened Raman intensities in arbitrary units integrated over all possible
        orientation to reproduce the powder measurements for frequencies in an interval. It is possible to
        use the susceptibilities from the transverse modes only or to specify one of the directions with non
        analytical contributions.

        Args:
            temp: temperature in K.
            laser_freq: frequency of the incident laser. The units are determined the "units"
                argument.
            width: the width of the Lorentz distribution. The units are determined the "units"
                argument.
            non_anal_dir: index of the direction along which the non analytical contribution
                has been calculated. Corresponds to the indices in the non_anal_directions attribute.
            min_freq: minimum frequency considered. If None it will be given by the minimum
                frequency with non zero intensities minus 10 times the width of the distribution.
                If given the units are determined by the "units" argument.
            max_freq: maximum frequency considered. If None it will be given by the maximum
                frequency with non zero intensities plus 10 times the width of the distribution.
                If given the units are determined by the "units" argument.
            num: number of frequencies in the interval (min_freq, max_freq).
            relative: if True the intensities will be rescaled so that the largest value of the
                total intensity is 1.
            units: the units in which the input and the output frequencies will be given.
                Possible values in ("eV", "meV", "Ha", "cm-1", "Thz")

        Returns:
            A PowderIntensity with the parallel, perpendicular and total components of the powder
            intensities. Each one is a Function1D with "num" points.
        """

        pi = self.get_powder_intensity(temp=temp,
                                       laser_freq=laser_freq,
                                       non_anal_dir=non_anal_dir,
                                       units=units)

        freqs, lorentz = self._get_lorentz_freqs_and_factor(
            intensity=pi.tot,
            non_anal_dir=non_anal_dir,
            min_freq=min_freq,
            max_freq=max_freq,
            num=num,
            width=width,
            units=units)

        lpi = np.array([i.dot(lorentz) for i in pi])
        if relative:
            lpi /= lpi[2].max()

        # now convert the frequencies to the desired units for the output
        x = freqs * abu.phfactor_ev2units(units)

        return PowderIntensity(*(Function1D(x, y) for y in lpi))
コード例 #17
0
ファイル: plot_funcs.py プロジェクト: akakcolin/abipy
#!/usr/bin/env python
#
# This example shows how to use the Function1D object to analyze and plot results.
import numpy as np
import matplotlib.pyplot as plt

from abipy.core.func1d import Function1D

# Build mesh [0, 2pi] with 100 points.
mesh = np.linspace(0, 2*np.pi, num=100)

# Compute sine function.
sine = Function1D.from_func(np.sin, mesh)

# Call matplotlib to plot data.
fig = plt.figure()
ax = fig.add_subplot(1,1,1)

# Plot sine.
sine.plot_ax(ax, label="sin(x)")

# Spline sine on the coarse mesh sx, and plot the data.
sx = np.linspace(0, 2*np.pi, num=25)
splsine = sine.spline(sx) 

plt.plot(sx, splsine, "ro", label="splined sine")

# Compute the 1-st and 2-nd order derivatives 
# with finite differences (5-point stencil).
for order in [1,2]:
    der = sine.finite_diff(order=order)
コード例 #18
0
#!/usr/bin/env python
import wx
import numpy as np

from abipy.core.func1d import Function1D
from abipy.gui.awx.func1dframe import Func1dPlotFrame

app = wx.App()
func1d = Function1D.from_func(np.sin, np.arange(1, 100, 1))
frame = Func1dPlotFrame(None, func1d)
frame.Show()
app.MainLoop()
コード例 #19
0
ファイル: gw.py プロジェクト: gmrigna/abipy
    def __init__(self, spin, kpoint, band, wmesh, sigmaxc_values, spfunc_values):
        self.spin, self.kpoint, self.band = spin, kpoint, band
        self.wmesh = np.array(wmesh)

        self.xc = Function1D(self.wmesh, sigmaxc_values)
        self.spfunc = Function1D(self.wmesh, spfunc_values)
コード例 #20
0
    def ae_core_density_on_mesh(cls, valence_density, structure, rhoc_files, maxr=2.0, nelec=None,
                                method='mesh3d_dist_gridpoints', small_dist_mesh=(8, 8, 8), small_dist_factor=1.5):
        """
        Initialize the all electron core density of the structure from the pseudopotentials *rhoc* files
        Note that these *rhoc* files contain one column with the radii in Bohrs and one column with the density
        in #/Bohr^3 multiplied by a factor 4pi.
        """
        rhoc_atom_splines = [None]*len(structure)
        if isinstance(rhoc_files, (list, tuple)):
            if len(structure) != len(rhoc_files):
                raise ValueError('Number of rhoc_files should be equal to the number of sites in the structure')
            for ifname, fname in rhoc_files:
                rad_rho = np.fromfile(fname, sep=' ')
                rad_rho = rad_rho.reshape((len(rad_rho)/2, 2))
                radii = rad_rho[:, 0] * bohr_to_angstrom
                rho = rad_rho[:, 1] / (4.0*np.pi) / (bohr_to_angstrom ** 3)
                func1d = Function1D(radii, rho)
                rhoc_atom_splines[ifname] = func1d.spline

        elif isinstance(rhoc_files, collections.Mapping):
            atoms_symbols = [elmt.symbol for elmt in structure.composition]
            if not np.all([atom in rhoc_files for atom in atoms_symbols]):
                raise ValueError('The rhoc_files should be provided for all the atoms in the structure')
            splines = {}
            for symbol, fname in rhoc_files.items():
                rad_rho = np.fromfile(fname, sep=' ')
                rad_rho = rad_rho.reshape((len(rad_rho)/2, 2))
                radii = rad_rho[:, 0] * bohr_to_angstrom
                rho = rad_rho[:, 1] / (4.0*np.pi) / (bohr_to_angstrom ** 3)
                func1d = Function1D(radii, rho)
                splines[symbol] = func1d.spline
            for isite, site in enumerate(structure):
                rhoc_atom_splines[isite] = splines[site.specie.symbol]

        core_den = np.zeros_like(valence_density.datar)
        dvx = valence_density.mesh.dvx
        dvy = valence_density.mesh.dvy
        dvz = valence_density.mesh.dvz
        maxdiag = max([np.linalg.norm(dvx+dvy+dvz),
                       np.linalg.norm(dvx+dvy-dvz),
                       np.linalg.norm(dvx-dvy+dvz),
                       np.linalg.norm(dvx-dvy-dvz)])
        smallradius = small_dist_factor*maxdiag

        if method == 'get_sites_in_sphere':
            for ix in range(valence_density.mesh.nx):
                for iy in range(valence_density.mesh.ny):
                    for iz in range(valence_density.mesh.nz):
                        rpoint = valence_density.mesh.rpoint(ix=ix, iy=iy, iz=iz)
                        # TODO: optimize this !
                        sites = structure.get_sites_in_sphere(pt=rpoint, r=maxr, include_index=True)
                        for site, dist, site_index in sites:
                            if dist > smallradius:
                                core_den[0, ix, iy, iz] += rhoc_atom_splines[site_index](dist)
                            # For small distances, integrate over the small volume dv around the point as the core
                            # density is extremely high close to the atom
                            else:
                                total = 0.0
                                nnx, nny, nnz = small_dist_mesh
                                ddvx = dvx/nnx
                                ddvy = dvy/nny
                                ddvz = dvz/nnz
                                rpi = rpoint - 0.5 * (dvx + dvy + dvz) + 0.5*ddvx + 0.5*ddvy + 0.5*ddvz
                                for iix in range(nnx):
                                    for iiy in range(nny):
                                        for iiz in range(nnz):
                                            rpoint2 = rpi + iix*ddvx + iiy*ddvy + iiz*ddvz
                                            dist2 = np.linalg.norm(rpoint2 - site.coords)
                                            total += rhoc_atom_splines[site_index](dist2)
                                total /= (nnx*nny*nnz)
                                core_den[0, ix, iy, iz] += total

        elif method == 'mesh3d_dist_gridpoints':
            site_coords = [site.coords for site in structure]
            dist_gridpoints_sites = valence_density.mesh.dist_gridpoints_in_spheres(points=site_coords, radius=maxr)
            for isite, dist_gridpoints_site in enumerate(dist_gridpoints_sites):
                for igp_uc, dist, igp in dist_gridpoints_site:
                    if dist > smallradius:
                        core_den[0, igp_uc[0], igp_uc[1], igp_uc[2]] += rhoc_atom_splines[isite](dist)
                    # For small distances, integrate over the small volume dv around the point as the core density
                    # is extremely high close to the atom
                    else:
                        total = 0.0
                        nnx, nny, nnz = small_dist_mesh
                        ddvx = dvx/nnx
                        ddvy = dvy/nny
                        ddvz = dvz/nnz
                        rpoint = valence_density.mesh.rpoint(ix=igp[0], iy=igp[1], iz=igp[2])
                        rpi = rpoint - 0.5 * (dvx + dvy + dvz) + 0.5*ddvx + 0.5*ddvy + 0.5*ddvz
                        for iix in range(nnx):
                            for iiy in range(nny):
                                for iiz in range(nnz):
                                    rpoint2 = rpi + iix*ddvx + iiy*ddvy + iiz*ddvz
                                    dist2 = np.linalg.norm(rpoint2 - site_coords[isite])
                                    total += rhoc_atom_splines[isite](dist2)
                        total /= (nnx*nny*nnz)
                        core_den[0, igp_uc[0], igp_uc[1], igp_uc[2]] += total
        else:
            raise ValueError('Method "{}" is not allowed'.format(method))

        if nelec is not None:
            sum_elec = np.sum(core_den)*valence_density.mesh.dv
            if np.abs(sum_elec-nelec) / nelec > 0.01:
                raise ValueError('Summed electrons is different from the actual number of electrons by '
                                 'more than 1% ...')
            core_den = core_den / sum_elec * nelec

        return cls(nspinor=1, nsppol=1, nspden=1, rhor=core_den, structure=structure, iorder='c')