Ejemplo n.º 1
0
    def finite_diff(self, values, order=1, acc=4):
        """
        Compute the derivatives of values by finite differences.

        Args:
            values: array-like object with the values of the path.
            order: Order of the derivative.
            acc: Accuracy: 4 corresponds to a central difference with 5 points.

        Returns:
            ndarray with the derivative.
        """
        values = np.asarray(values)
        assert len(values) == len(self)

        # Loop over the lines of the path, extract the data and
        # differenciate f(s) where s is the distance along the line.
        ders_on_lines = []

        for line in self.lines:
            vals_on_line = values[line]
            h = self.ds[line[0]]

            if not np.allclose(h, self.ds[line[:-1]]):
                raise ValueError("For finite difference derivatives, the path must be homogeneous!\n" +
                                 str(self.ds[line[:-1]]))

            der = finite_diff(vals_on_line, h, order=order, acc=acc)
            ders_on_lines.append(der)

        return np.array(ders_on_lines)
Ejemplo n.º 2
0
    def plot_der_potentials(self, ax=None, order=1, **kwargs):
        """
        Plot the derivatives of vl and vloc potentials on axis ax.
        Used to analyze the derivative discontinuity introduced by the RRKJ method at rc.
        """
        ax, fig, plt = get_ax_fig_plt(ax)
        from abipy.tools.derivatives import finite_diff
        from scipy.interpolate import UnivariateSpline
        lines, legends = [], []
        for l, pot in self.potentials.items():
            # Need linear mesh for finite_difference --> Spline input potentials on lin_rmesh
            lin_rmesh, h = np.linspace(pot.rmesh[0], pot.rmesh[-1], num=len(pot.rmesh) * 4, retstep=True)
            spline = UnivariateSpline(pot.rmesh, pot.values, s=0)
            lin_values = spline(lin_rmesh)
            vder = finite_diff(lin_values, h, order=order, acc=4)
            line, = ax.plot(lin_rmesh, vder, **self._wf_pltopts(l, "ae"))
            lines.append(line)

            if l == -1:
                legends.append("%s-order derivative Vloc" % order)
            else:
                legends.append("$s-order derivative PS l=%s" % str(l))

        decorate_ax(ax, xlabel="r [Bohr]", ylabel="$D^%s \phi(r)$" % order,
                    title="Derivative of the ion Pseudopotentials",
                    lines=lines, legends=legends)
        return fig
Ejemplo n.º 3
0
    def finite_diff(self, values, order=1, acc=4):
        """
        Compute the derivatives of values by finite differences.

        Args:
            values: array-like object with the values of the path.
            order: Order of the derivative.
            acc: Accuracy: 4 corresponds to a central difference with 5 points.

        Returns:
            ndarray with the derivative.
        """
        values = np.asarray(values)
        assert len(values) == len(self)

        # Loop over the lines of the path, extract the data and
        # differenciate f(s) where s is the distance along the line.
        ders_on_lines = []

        for line in self.lines:
            vals_on_line = values[line]
            h = self.ds[line[0]]

            if not np.allclose(h, self.ds[line[:-1]]):
                raise ValueError(
                    "For finite difference derivatives, the path must be homogeneous!\n"
                    + str(self.ds[line[:-1]]))

            der = finite_diff(vals_on_line, h, order=order, acc=acc)
            ders_on_lines.append(der)

        return np.array(ders_on_lines)
Ejemplo n.º 4
0
    def test_poly(self):
        """Test derivatives of polynomials."""
        x, h = np.linspace(0, 1, 800, retstep=True)
        orders = [1, 2, 3, 4]
        accuracies = [2, 4, 6]

        f = x**4
        dpolys = {
            1: 4 * x**3,
            2: 12 * x**2,
            3: 24 * x,
            4: 24 * np.ones(len(x)),
        }

        decs = {
            1: 5,
            2: 4,
            3: 4,
            4: 1,
        }

        for order in orders:
            for acc in accuracies:
                if order == 4 and acc == 6: continue
                print("order %s, acc %s" % (order, acc))
                yder = finite_diff(f, h, order=order, acc=acc)
                print(np.max(np.abs(yder - dpolys[order])))
                self.assert_almost_equal(yder,
                                         dpolys[order],
                                         decimal=decs[order])
Ejemplo n.º 5
0
    def plot_der_potentials(self, ax=None, order=1, **kwargs):
        """
        Plot the derivatives of vl and vloc potentials on axis ax.
        Used to analyze the derivative discontinuity introduced by the RRKJ method at rc.
        """
        ax, fig, plt = get_ax_fig_plt(ax)
        from abipy.tools.derivatives import finite_diff
        from scipy.interpolate import UnivariateSpline
        lines, legends = [], []
        for l, pot in self.potentials.items():
            # Need linear mesh for finite_difference --> Spline input potentials on lin_rmesh
            lin_rmesh, h = np.linspace(pot.rmesh[0], pot.rmesh[-1], num=len(pot.rmesh) * 4, retstep=True)
            spline = UnivariateSpline(pot.rmesh, pot.values, s=0)
            lin_values = spline(lin_rmesh)
            vder = finite_diff(lin_values, h, order=order, acc=4)
            line, = ax.plot(lin_rmesh, vder, **self._wf_pltopts(l, "ae"))
            lines.append(line)

            if l == -1:
                legends.append("%s-order derivative Vloc" % order)
            else:
                legends.append("$s-order derivative PS l=%s" % str(l))

        decorate_ax(ax, xlabel="r [Bohr]", ylabel="$D^%s \phi(r)$" % order,
                    title="Derivative of the ion Pseudopotentials",
                    lines=lines, legends=legends)
        return fig
Ejemplo n.º 6
0
    def plot_der_densities(self, ax=None, order=1, **kwargs):
        """
        Plot the derivatives of the densitiers on axis ax.
        Used to analyze possible derivative discontinuities
        """
        ax, fig, plt = get_ax_fig_plt(ax)

        from scipy.interpolate import UnivariateSpline

        lines, legends = [], []
        for name, rho in self.densities.items():
            if name != "rhoM": continue
            # Need linear mesh for finite_difference --> Spline input densities on lin_rmesh
            lin_rmesh, h = np.linspace(rho.rmesh[0], rho.rmesh[-1], num=len(rho.rmesh) * 4, retstep=True)
            spline = UnivariateSpline(rho.rmesh, rho.values, s=0)
            lin_values = spline(lin_rmesh)
            vder = finite_diff(lin_values, h, order=order, acc=4)
            line, = ax.plot(lin_rmesh, vder) #, **self._wf_pltopts(l, "ae"))
            lines.append(line)

            legends.append("%s-order derivative of %s" % (order, name))

        decorate_ax(ax, xlabel="r [Bohr]", ylabel="$D^%s \n(r)$" % order, title="Derivative of the charge densities",
                    lines=lines, legends=legends)
        return fig
Ejemplo n.º 7
0
    def test_poly(self):
        """Test derivatives of polynomials."""
        x, h = np.linspace(0, 1,  800, retstep=True)
        orders = [1,2,3,4]
        accuracies = [2,4,6]

        f = x**4
        dpolys = {
            1: 4 * x**3,
            2: 12 * x**2,
            3: 24 * x,
            4: 24 * np.ones(len(x)),
        }

        decs = {
            1: 5,
            2: 4,
            3: 4,
            4: 1,
        }

        for order in orders:
            for acc in accuracies:
                if order == 4 and acc == 6: continue
                print("order %s, acc %s" % (order, acc))
                yder = finite_diff(f, h, order=order, acc=acc)
                print(np.max(np.abs(yder - dpolys[order])))
                self.assert_almost_equal(yder, dpolys[order], decimal=decs[order])
Ejemplo n.º 8
0
    def plot_der_densities(self, ax=None, order=1, **kwargs):
        """
        Plot the derivatives of the densitiers on axis ax.
        Used to analyze possible derivative discontinuities
        """
        ax, fig, plt = get_ax_fig_plt(ax)

        from scipy.interpolate import UnivariateSpline

        lines, legends = [], []
        for name, rho in self.densities.items():
            if name != "rhoM": continue
            # Need linear mesh for finite_difference --> Spline input densities on lin_rmesh
            lin_rmesh, h = np.linspace(rho.rmesh[0], rho.rmesh[-1], num=len(rho.rmesh) * 4, retstep=True)
            spline = UnivariateSpline(rho.rmesh, rho.values, s=0)
            lin_values = spline(lin_rmesh)
            vder = finite_diff(lin_values, h, order=order, acc=4)
            line, = ax.plot(lin_rmesh, vder) #, **self._wf_pltopts(l, "ae"))
            lines.append(line)

            legends.append("%s-order derivative of %s" % (order, name))

        decorate_ax(ax, xlabel="r [Bohr]", ylabel="$D^%s \n(r)$" % order, title="Derivative of the charge densities",
                    lines=lines, legends=legends)
        return fig
Ejemplo n.º 9
0
 def get_fd_emass_d2(self, enes_kline, acc):
     d2 = finite_diff(enes_kline,
                      self.dk,
                      order=2,
                      acc=acc,
                      index=self.kpos)
     emass = 1. / (d2.value * (units.eV_to_Ha / units.bohr_to_ang**2))
     return emass, d2
Ejemplo n.º 10
0
    def finite_diff(self, order=1, acc=4):
        """
        Compute the derivatives by finite differences.

        Args:
            order: Order of the derivative.
            acc: Accuracy. 4 is fine in many cases.

        Returns:
            new :class:`Function1d` instance with the derivative.
        """
        if self.h is None:
            raise ValueError("Finite differences with inhomogeneous meshes are not supported")

        return self.__class__(self.mesh, finite_diff(self.values, self.h, order=order, acc=acc))
Ejemplo n.º 11
0
    def test_exp(self):
        """Test derivatives of exp(x)."""
        x, h = np.linspace(0, 2, 800, retstep=True)
        orders = [1,2,3,4]
        accuracies = [2,4,6]
        exp = np.exp(x)

        decs = {
            1: 4,
            2: 4,
            3: 4,
            4: 2,
        }

        for order in orders:
            for acc in accuracies:
                if order == 4 and acc == 6: continue
                #print("order %s, acc %s" % (order, acc))
                yder = finite_diff(exp, h, order=order, acc=acc)
                #print(np.max(np.abs(yder - exp)))
                self.assert_almost_equal(yder, exp, decs[order])

                d = finite_diff(exp, h, order=order, acc=acc, index=100)
                assert yder[100] == d.value
Ejemplo n.º 12
0
    def test_exp(self):
        """Test derivatives of exp(x)."""
        x, h = np.linspace(0, 2,  800, retstep=True)
        orders = [1,2,3,4]
        accuracies = [2,4,6]
        exp = np.exp(x)

        decs = {
            1: 4,
            2: 4,
            3: 4,
            4: 2,
        }

        for order in orders:
            for acc in accuracies:
                if order == 4 and acc == 6: continue
                print("order %s, acc %s" % (order, acc))
                yder = finite_diff(exp, h, order=order, acc=acc)
                print(np.max(np.abs(yder - exp)))
                self.assert_almost_equal(yder, exp, decs[order])
Ejemplo n.º 13
0
def calculate_gruns_finite_differences(phfreqs, eig, iv0, volume, dv):
    """
    Calculates the Gruneisen parameters from finite differences on the phonon frequencies.
    Uses the eigenvectors to match the frequencies at different volumes.

    Args:
        phfreqs: numpy array with the phonon frequencies at different volumes. Shape (nvols, nqpts, 3*natoms)
        eig: numpy array with the phonon eigenvectors at the different volumes. Shape (nvols, nqpts, 3*natoms, 3*natoms)
            If None simple ordering will be used.
        iv0: index of the 0 volume.
        volume: volume of the structure at the central volume.
        dv: volume variation.

    Returns:
        A numpy array with the gruneisen parameters. Shape (nqpts, 3*natoms)
    """
    phfreqs = phfreqs.copy()

    nvols = phfreqs.shape[0]
    if eig is not None:
        for i in range(nvols):
            if i == iv0:
                continue
            for iq in range(phfreqs.shape[1]):
                ind = match_eigenvectors(eig[iv0, iq], eig[i, iq])
                phfreqs[i, iq] = phfreqs[i, iq][ind]

    acc = nvols - 1
    g = np.zeros_like(phfreqs[0])
    for iq in range(phfreqs.shape[1]):
        for im in range(phfreqs.shape[2]):
            w = phfreqs[iv0, iq, im]
            if w == 0:
                g[iq, im] = 0
            else:
                g[iq, im] = -finite_diff(
                    phfreqs[:, iq, im], dv, order=1, acc=acc)[iv0] * volume / w

    return g
Ejemplo n.º 14
0
def calculate_gruns_finite_differences(phfreqs, eig, iv0, volume, dv):
    """
    Calculates the Gruneisen parameters from finite differences on the phonon frequencies. Uses the eigenvectors
    to match the frequencies at different volumes.

    Args:
        phfreqs: numpy array with the phonon frequencies at different volumes. Shape (nvols, nqpts, 3*natoms)
        eig: numpy array with the phonon eigenvectors at the different volumes. Shape (nvols, nqpts, 3*natoms, 3*natoms)
            If None simple ordering will be used.
        iv0: index of the 0 volume.
        volume: volume of the structure at the central volume.
        dv: volume variation.

    Returns:
        A numpy array with the gruneisen parameters. Shape (nqpts, 3*natoms)
    """
    phfreqs = phfreqs.copy()

    nvols = phfreqs.shape[0]
    if eig is not None:
        for i in range(nvols):
            if i == iv0:
                continue
            for iq in range(phfreqs.shape[1]):
                ind = match_eigenvectors(eig[iv0, iq], eig[i, iq])
                phfreqs[i, iq] = phfreqs[i, iq][ind]

    acc = nvols - 1
    g = np.zeros_like(phfreqs[0])
    for iq in range(phfreqs.shape[1]):
        for im in range(phfreqs.shape[2]):
            w = phfreqs[iv0, iq, im]
            if w == 0:
                g[iq, im] = 0
            else:
                g[iq, im] = - finite_diff(phfreqs[:, iq, im], dv, order=1, acc=acc)[iv0] * volume / w

    return g
Ejemplo n.º 15
0
 def test_complex(self):
     """complex functions are not supported"""
     x, h = np.linspace(0, 1, 800, retstep=True)
     cf = 1j * x
     with self.assertRaises(ValueError):
         return finite_diff(cf, h)
Ejemplo n.º 16
0
 def test_complex(self):
     """complex functions are not supported"""
     x, h = np.linspace(0, 1,  800, retstep=True)
     cf = 1j*x
     with self.assertRaises(ValueError):
         return finite_diff(cf, h)