def test_eos_fit_deriv(): data = np.loadtxt("files/ev/evdata.txt") volume = data[:,0] * Bohr3_to_Ang3 energy = data[:,1] * (Ry / eV) eos = EosFit(volume=volume, energy=energy, splpoints=500) # EosFit is a num.Fit1D subclass, so it has self.x and self.y assert (volume == eos.x).all() assert (energy == eos.y).all() # this reference to self.spl causes self.spl to be defined (lazyprop) xx = eos.spl.x yy = eos.spl.y assert len(xx) == len(yy) == 500 # spline thru fitted data, must be exactly like eos.spl spl = num.Spline(xx, yy, k=5, s=None) assert np.allclose(eos(xx), yy) # call _vinet, consistency of fitted data assert np.allclose(eos(xx), spl(xx)) # consistency of splines assert np.allclose(eos(xx), eos.spl(xx)) # consistency of splines assert np.allclose(eos(xx, der=1), spl(xx, der=1)) # call _vinet_deriv1 assert np.allclose(eos(xx, der=2), spl(xx, der=2)) # call _vinet_deriv2 assert np.allclose(eos(xx, der=3), spl(xx, der=3)) # call eos.spl(xx, der=3)
def _get_spl(self, attr_name): # attr_name : 'ev', 'pv', 'bv' # spl_attr_name : 'self.spl_{ev,pv,bv}' spl_attr_name = "spl_%s" % attr_name if self.is_set_attr(spl_attr_name): return getattr(self, spl_attr_name) else: arr = getattr(self, attr_name) return num.Spline(arr[:, 0], arr[:, 1])
def test_gibbs(): # number of varied axis points nax = 6 # phonon freq axis freq = np.linspace(0, 1000, 300) # cm^-1 T = np.linspace(5, 2000, 50) P = np.linspace(0, 5, 2) # 2d case case = '2d' cell_a = np.linspace(2.5, 3.5, nax) cell_c = np.linspace(3, 3.8, nax) volfunc_ax = lambda x: x[0]**2 * x[1] axes_flat = np.array([x for x in product(cell_a, cell_c)]) V = np.array([volfunc_ax(x) for x in axes_flat]) cell_a_mean = cell_a.mean() cell_c_mean = cell_c.mean() cell_a_min = cell_a.min() cell_c_min = cell_c.min() etot = np.array([(a - cell_a_mean)**2.0 + (c - cell_c_mean)**2.0 for a, c in axes_flat]) phdos = [] Vmax = V.max() # phonon dos (just a gaussian) shifted to lower (higher) freqs for higher # (lower) volume for ii in range(axes_flat.shape[0]): a, c = axes_flat[ii, :] fc = 550 - 50 * V[ii] / Vmax phdos.append(np.array([freq, gauss(freq - fc, 100) * 0.01]).T) gibbs = Gibbs(T=T, P=P, etot=etot, phdos=phdos, axes_flat=axes_flat, volfunc_ax=volfunc_ax, case=case, dosarea=None) gibbs.set_fitfunc('C', lambda x, y: num.Spline(x, y, s=None, k=5, eps=1e-5)) g = gibbs.calc_G(calc_all=True) dr = 'files/gibbs/2d' for name in os.listdir(dr): fn = '%s/%s' % (dr, name) gref = io.read_h5(fn) print("testing: %s" % fn) compare_dicts_with_arrays(gref, g) tools.assert_dict_with_all_types_almost_equal(gref, g, keys=list(gref.keys()), atol=1e-8, rtol=1e-3) # 1d case case = '1d' V = np.linspace(10, 20, nax) axes_flat = V**(1 / 3.) # cubic volfunc_ax = lambda x: x[0]**3.0 etot = (V - V.mean())**2 fcenter = 450 + 100 * (axes_flat - axes_flat.min()) # fake phonon dos data (Gaussian), shift to lower freq for higher volume phdos = [np.array([freq, gauss(freq - fc, 100)]).T for fc in fcenter[::-1]] gibbs = Gibbs(T=T, P=P, etot=etot, phdos=phdos, axes_flat=axes_flat, volfunc_ax=volfunc_ax, case=case, dosarea=None) gibbs.set_fitfunc('C', lambda x, y: num.Spline(x, y, s=None, k=5, eps=1e-5)) g = gibbs.calc_G(calc_all=True) dr = 'files/gibbs/1d' for name in os.listdir(dr): fn = '%s/%s' % (dr, name) gref = io.read_h5(fn) print("testing: %s" % fn) compare_dicts_with_arrays(gref, g) tools.assert_dict_with_all_types_almost_equal(gref, g, keys=list(gref.keys()), atol=1e-14, rtol=1e-8) # test enthalpy stuff for 1d case # E(V) ev = num.PolyFit1D(g['/ax0/V'], g['/ax0/Etot'], deg=5) # P(V) pv = lambda v: -ev(v, der=1) * constants.eV_by_Ang3_to_GPa assert np.allclose(g['/P/P'], pv(g['/#opt/P/V'])) assert np.allclose(g['/#opt/P/H'], ev(g['/#opt/P/V']) + g['/P/P']*g['/#opt/P/V'] / \ constants.eV_by_Ang3_to_GPa)
# (lower) volume for ii in range(axes_flat.shape[0]): a, c = axes_flat[ii, :] fc = 550 - 50 * V[ii] / Vmax phdos.append(np.array([freq, gauss(freq - fc, 100) * 0.01]).T) gibbs = Gibbs(T=T, P=P, etot=etot, phdos=phdos, axes_flat=axes_flat, volfunc_ax=volfunc_ax, case=case, dosarea=None) gibbs.set_fitfunc('C', lambda x, y: num.Spline(x, y, s=None, k=5, eps=1e-5)) g = gibbs.calc_G(calc_all=True) common.makedirs('../files/gibbs/2d') io.write_h5('../files/gibbs/2d/%s.h5' % gethostname(), filt_dct(g), mode='w') # 1d case case = '1d' V = np.linspace(10, 20, nax) axes_flat = V**(1 / 3.) # cubic volfunc_ax = lambda x: x[0]**3.0 etot = (V - V.mean())**2 fcenter = 450 + 100 * (axes_flat - axes_flat.min()) # fake phonon dos data (Gaussian), shift to lower freq for higher volume phdos = [np.array([freq, gauss(freq - fc, 100)]).T for fc in fcenter[::-1]]
def find_peaks(y, x=None, k=3, spread=2, ymin=None): """Simple peak finding algorithm. Find all peaks where ``y > ymin``. If `x` given, also extract peak maxima positions by fitting a spline of order `k` to each found peak. To find minima, just use ``-y``. Parameters ---------- y : 1d array_like data with peaks x : 1d array_like, optional, len(y) x axis k : int order of spline spread : int Use ``2*spread+1`` points around each peak to fit a spline. Note that we need ``2*spread+1 > k``. ymin : float, optional Find all peaks above that value. Returns ------- idx0, pos0 idx0 : indices of peaks from finite diffs, each peak is at ``x[idx0[i]]`` pos0 : refined `x`-positions of peaks if `x` given, else None Examples -------- >>> from pwtools.signal import gauss, find_peaks >>> from pwtools import num >>> x=linspace(0,10,300); y=0.2*gauss(x-0.5,.1) + gauss(x-2,.1) + 0.7*gauss(x-3,0.1) + gauss(x-6,1) >>> # ymin=0.4: ignore first peak at x=0.5 >>> find_peaks(y,x, ymin=0.4) ([60, 90, 179], [2.000231296097065, 3.0007122565950572, 5.999998055132549]) >>> idx0, pos0=find_peaks(y,x, ymin=0.4) >>> spl=num.Spline(x,y) >>> plot(x,y) >>> for x0 in pos0: ... plot([x0], [spl(x0)], 'ro') """ ymin = y.min() if ymin is None else ymin idx0 = [] dfy = np.diff(y, n=1) for ii in range(len(dfy) - 1): if dfy[ii] > 0 and dfy[ii + 1] < 0 and y[ii] >= ymin: idx0.append(ii + 1) pos0 = None if x is not None: pos0 = [] for i0 in idx0: sl = slice(i0 - spread, i0 + 1 + spread, None) xx = x[sl] yy = y[sl] spl = num.Spline(xx, -yy, k=k, s=None) try: root = spl.get_min() pos0.append(root) except ValueError: raise ValueError( "error calculating spline maximum at idx=%i, x=%f" % (i0, x[i0])) return idx0, pos0
def spl(self): """Spline thru the fitted E(V) b/c we are too lazy to calculate the analytic derivative. Fallback.""" # use many points for accurate deriv vv = np.linspace(self.volume.min(), self.volume.max(), self.splpoints) return num.Spline(vv, self(vv, der=0), k=5, s=None)
def _default_fit_C(x, y): return num.Spline(x, y, k=5, s=None)