示例#1
0
def test_get_ase_atoms():
    natoms = 10
    st = crys.Structure(coords_frac=rand(natoms,3),
                        symbols=['H']*10,
                        cell=rand(3,3))
    try:
        import ase
        st2 = crys.atoms2struct(crys.struct2atoms(st))
        keys = ['natoms', 'coords', 'coords_frac', 'symbols', 'cryst_const',
                'cell', 'volume', 'mass']
        tools.assert_dict_with_all_types_almost_equal(\
            st.__dict__,
            st2.__dict__,
            keys=keys,
            strict=True)
        # in case the test fails, use this to find out which key failed            
##        for kk in keys:
##            print("testing: %s ..." %kk)
##            tools.assert_all_types_almost_equal(st.__dict__[kk], st2.__dict__[kk])
        for pbc in [True,False]:
            at = st.get_ase_atoms(pbc=pbc)
            assert (at.pbc == np.array([pbc]*3)).all()
            at = crys.struct2atoms(st, pbc=pbc)
            assert (at.pbc == np.array([pbc]*3)).all()
    except ImportError:
        tools.skip("cannot import ase, skipping test get_ase_atoms()")
示例#2
0
def test_get_ase_atoms():
    natoms = 10
    st = crys.Structure(coords_frac=rand(natoms, 3),
                        symbols=['H'] * 10,
                        cell=rand(3, 3))
    try:
        import ase
        st2 = crys.atoms2struct(crys.struct2atoms(st))
        keys = [
            'natoms', 'coords', 'coords_frac', 'symbols', 'cryst_const',
            'cell', 'volume', 'mass'
        ]
        tools.assert_dict_with_all_types_almost_equal(\
            st.__dict__,
            st2.__dict__,
            keys=keys,
            strict=True)
        # in case the test fails, use this to find out which key failed
        ##        for kk in keys:
        ##            print("testing: %s ..." %kk)
        ##            tools.assert_all_types_almost_equal(st.__dict__[kk], st2.__dict__[kk])
        for pbc in [True, False]:
            at = st.get_ase_atoms(pbc=pbc)
            assert (at.pbc == np.array([pbc] * 3)).all()
            at = crys.struct2atoms(st, pbc=pbc)
            assert (at.pbc == np.array([pbc] * 3)).all()
    except ImportError:
        tools.skip("cannot import ase, skipping test get_ase_atoms()")
示例#3
0
def test_plot_dis():
    spp = kpath.SpecialPointsPath(ks=np.array([[0,0,0], [.5,0,0], [.7,0,0]]),
                                  ks_frac=np.array([[0,0,0], [.55,0,0], [.77,0,0]]),  
                                  symbols=['A','B', 'C'])
    path_norm = np.linspace(0,1,100)
    nfreq = 5
    freqs = np.random.rand(100, nfreq) 
    try:
        print os.environ['DISPLAY']
        fig1,ax1,axdos1 = kpath.plot_dis(path_norm, freqs, spp,
                                         show_coords='cart')
        assert axdos1 is None
        fig2,ax2 = mpl.fig_ax()
        kpath.plot_dis(path_norm, freqs, spp, ax=ax2, show_coords='frac')
        lines1 = ax1.get_lines()
        lines2 = ax2.get_lines()
        for idx in range(nfreq):
            x1 = lines1[idx].get_xdata()
            x2 = lines2[idx].get_xdata()
            y1 = lines1[idx].get_ydata()
            y2 = lines2[idx].get_ydata()
            assert (x1 == x2).all()
            assert (y1 == y2).all()
        faxis = np.linspace(freqs.min(), freqs.max(), 30)                
        dos = np.array([faxis, np.random.rand(len(faxis))]).T            
        fig3,ax3,ax3dos = kpath.plot_dis(path_norm, freqs, spp, dos=dos,
                                         show_coords=None)
        # plot 90 rotated -> x and y swapped
        assert (ax3dos.get_lines()[0].get_xdata() == dos[:,1]).all()
        assert (ax3dos.get_lines()[0].get_ydata() == dos[:,0]).all()
    except KeyError:
        tools.skip("no DISPLAY environment variable, skipping test")
示例#4
0
def test_interpol2d_CloughTocher():
    dd, tgt = get_test_data()
    try:
        from scipy.interpolate import CloughTocher2DInterpolator
        inter = num.Interpol2D(dd=dd, what='ct')
        assert np.allclose(inter([[-3,-4],[0,0]]), tgt,
            atol=1e-1)
        assert np.allclose(return_min(inter), 5.0, atol=1e-1)
        dump(inter)
    except ImportError:
        tools.skip("couldn't import scipy.interpolate.CloughTocher2DInterpolator")
示例#5
0
 def test_ct(self):
     try:
         from scipy.interpolate import CloughTocher2DInterpolator
         inter = num.Interpol2D(dd=self.dd, what='ct')
         assert np.allclose(inter([[-3, -4], [0, 0]]), self.tgt, atol=1e-1)
         assert np.allclose(return_min(inter), 5.0, atol=1e-1)
         assert np.allclose(inter(self.dd.XY), self.dd.zz)
         dump(inter)
     except ImportError:
         tools.skip(
             "couldn't import scipy.interpolate.CloughTocher2DInterpolator")
示例#6
0
def test_h5():
    try:
        import h5py
        dct1 = \
            {'/a': 'abcgs',
             '/b/c/x1': 3,
             '/b/c/x2': rand(2,3),
             }
        # writing a dct w/o leading slash will always be read back in *with*
        # leading slash
        dct2 = \
            {'a': 'abciqo4iki',
             'b/c/x1': 3,
             'b/c/x2': rand(2,3),
             }
        for idx, dct in enumerate([dct1, dct2]):
            h5fn = os.path.join(testdir, 'test_%i.h5' % idx)
            io.write_h5(h5fn, dct)
            read_dct = io.read_h5(h5fn)
            for kk in list(read_dct.keys()):
                assert kk.startswith('/')
            for kk in list(dct.keys()):
                key = '/' + kk if not kk.startswith('/') else kk
                tools.assert_all_types_equal(dct[kk], read_dct[key])

        # write mode='a', test appending
        h5fn = os.path.join(testdir, 'test_append.h5')
        io.write_h5(h5fn, {'/a': 1.0})
        read_dct = io.read_h5(h5fn)
        assert list(read_dct.keys()) == ['/a']
        assert read_dct['/a'] == 1.0
        # append '/b', using {'/a': 1.0, '/b': 2.0} would be an error since /a
        # already exists, use mode='w' then, but this overwrites all!
        io.write_h5(h5fn, {'/b': 2.0}, mode='a')
        read_dct2 = io.read_h5(h5fn)
        # sort(...): sort possible [/b, /a] -> [/a, /b]
        assert np.sort(np.array(list(
            read_dct2.keys()))).tolist() == ['/a', '/b']
        assert read_dct2['/a'] == 1.0
        assert read_dct2['/b'] == 2.0
        # overwrite
        io.write_h5(h5fn, {'/b': 22.0, '/c': 33.0}, mode='w')
        read_dct3 = io.read_h5(h5fn)
        assert np.sort(np.array(list(
            read_dct3.keys()))).tolist() == ['/b', '/c']

    except ImportError:
        tools.skip("skipping test_h5, no h5py importable")
示例#7
0
def test_h5():
    try:
        import h5py
        dct1 = \
            {'/a': 'abcgs',
             '/b/c/x1': 3,
             '/b/c/x2': rand(2,3),
             }
        # writing a dct w/o leading slash will always be read back in *with*
        # leading slash             
        dct2 = \
            {'a': 'abciqo4iki',
             'b/c/x1': 3,
             'b/c/x2': rand(2,3),
             }
        for idx,dct in enumerate([dct1, dct2]):             
            h5fn = os.path.join(testdir, 'test_%i.h5' %idx)
            io.write_h5(h5fn, dct)
            read_dct = io.read_h5(h5fn)
            for kk in read_dct.keys():
                assert kk.startswith('/')
            for kk in dct.keys():
                key = '/'+kk if not kk.startswith('/') else kk
                tools.assert_all_types_equal(dct[kk], read_dct[key])
        
        # write mode='a', test appending
        h5fn = os.path.join(testdir, 'test_append.h5')
        io.write_h5(h5fn, {'/a': 1.0})
        read_dct = io.read_h5(h5fn)
        assert read_dct.keys() == ['/a']
        assert read_dct['/a'] == 1.0
        # append '/b', using {'/a': 1.0, '/b': 2.0} would be an error since /a
        # already exists, use mode='w' then, but this overwrites all!
        io.write_h5(h5fn, {'/b': 2.0}, mode='a')
        read_dct2 = io.read_h5(h5fn)
        # sort(...): sort possible [/b, /a] -> [/a, /b]
        assert np.sort(np.array(read_dct2.keys())).tolist() == ['/a', '/b']
        assert read_dct2['/a'] == 1.0
        assert read_dct2['/b'] == 2.0
        # overwrite
        io.write_h5(h5fn, {'/b': 22.0, '/c': 33.0}, mode='w')
        read_dct3 = io.read_h5(h5fn)
        assert np.sort(np.array(read_dct3.keys())).tolist() == ['/b', '/c']

    except ImportError:
        tools.skip("skipping test_h5, no h5py importable")
示例#8
0
def test_pwscf_calculator():
    if not have_ase():
        skip("no ASE found, skipping test")
    elif not have_pwx():
        skip("no pw.x found, skipping test")
    else:
        pseudo_dir = pj(testdir, prefix, 'pseudo')
        print(common.backtick("mkdir -pv {p}; cp files/qe_pseudos/*.gz {p}/; \
            gunzip {p}/*".format(p=pseudo_dir)))
        at = get_atoms_with_calc_pwscf(pseudo_dir)

        print("scf")
        # trigger calculation here
        forces = at.get_forces()
        etot = at.get_potential_energy()
        stress = at.get_stress(voigt=False) # 3x3
        
        st = io.read_pw_scf(at.calc.label + '.out')
        assert np.allclose(forces, st.forces)
        assert np.allclose(etot, st.etot)
        assert np.allclose(st.stress, -stress * constants.eV_by_Ang3_to_GPa)
        
        # files/ase/pw.scf.out.start is a norm-conserving LDA struct,
        # calculated with pz-vbc.UPF, so the PBE vc-relax will make the cell
        # a bit bigger
        print("vc-relax")
        from ase.optimize import BFGS
        from ase.constraints import UnitCellFilter
        opt = BFGS(UnitCellFilter(at))
        cell = parse.arr2d_from_txt("""
            -1.97281509  0.          1.97281509
             0.          1.97281509  1.97281509
            -1.97281509  1.97281509  0.""")        
        assert np.allclose(cell, at.get_cell())
        opt.run(fmax=0.05) # run only 2 steps
        cell = parse.arr2d_from_txt("""
            -2.01837531  0.          2.01837531
             0.          2.01837531  2.01837531
            -2.01837531  2.01837531  0""")
        assert np.allclose(cell, at.get_cell())

        # at least 1 backup files must exist: pw.*.0 is the SCF run, backed up
        # in the first iter of the vc-relax
        assert os.path.exists(at.calc.infile + '.0')
示例#9
0
def test_pwscf_calculator():
    if not have_ase():
        skip("no ASE found, skipping test")
    elif not have_pwx():
        skip("no pw.x found, skipping test")
    else:
        pseudo_dir = pj(testdir, prefix, 'pseudo')
        print common.backtick("mkdir -pv {p}; cp files/qe_pseudos/*.gz {p}/; \
            gunzip {p}/*".format(p=pseudo_dir))
        at = get_atoms_with_calc_pwscf(pseudo_dir)

        print "scf"
        # trigger calculation here
        forces = at.get_forces()
        etot = at.get_potential_energy()
        stress = at.get_stress(voigt=False) # 3x3
        
        st = io.read_pw_scf(at.calc.label + '.out')
        assert np.allclose(forces, st.forces)
        assert np.allclose(etot, st.etot)
        assert np.allclose(st.stress, -stress * constants.eV_by_Ang3_to_GPa)
        
        # files/ase/pw.scf.out.start is a norm-conserving LDA struct,
        # calculated with pz-vbc.UPF, so the PBE vc-relax will make the cell
        # a bit bigger
        print "vc-relax"
        from ase.optimize import BFGS
        from ase.constraints import UnitCellFilter
        opt = BFGS(UnitCellFilter(at))
        cell = parse.arr2d_from_txt("""
            -1.97281509  0.          1.97281509
             0.          1.97281509  1.97281509
            -1.97281509  1.97281509  0.""")        
        assert np.allclose(cell, at.get_cell())
        opt.run(fmax=0.05) # run only 2 steps
        cell = parse.arr2d_from_txt("""
            -2.01837531  0.          2.01837531
             0.          2.01837531  2.01837531
            -2.01837531  2.01837531  0""")
        assert np.allclose(cell, at.get_cell())

        # at least 1 backup files must exist: pw.*.0 is the SCF run, backed up
        # in the first iter of the vc-relax
        assert os.path.exists(at.calc.infile + '.0')
示例#10
0
def test_mpl():
    try:
        from pwtools import mpl
        try:
            import os
            print(os.environ['DISPLAY'])
            fig,ax = mpl.fig_ax(dpi=15,num=20)
            assert fig.dpi == 15
            assert fig.number == 20
            
            pl = mpl.Plot(dpi=15,num=20)
            assert pl.fig.dpi == 15
            assert pl.fig.number == 20
            
            dct = mpl.prepare_plots(['test'], dpi=15,num=20)
            assert dct['test'].fig.dpi == 15
            assert dct['test'].fig.number == 20
        except KeyError:
            tools.skip("no DISPLAY environment variable, skipping test")
    except ImportError:
        tools.skipping("couldn't import matplotlib, skipping test")
示例#11
0
def test_mpl():
    try:
        from pwtools import mpl
        try:
            import os
            print os.environ['DISPLAY']
            fig,ax = mpl.fig_ax(dpi=15,num=20)
            assert fig.dpi == 15
            assert fig.number == 20
            
            pl = mpl.Plot(dpi=15,num=20)
            assert pl.fig.dpi == 15
            assert pl.fig.number == 20
            
            dct = mpl.prepare_plots(['test'], dpi=15,num=20)
            assert dct['test'].fig.dpi == 15
            assert dct['test'].fig.number == 20
        except KeyError:
            tools.skip("no DISPLAY environment variable, skipping test")
    except ImportError:
        tools.skipping("couldn't import matplotlib, skipping test")
示例#12
0
def test_lammps_calculator():
    if not have_ase():
        skip("no ASE found, skipping test")
    elif not have_lmp():
        skip("no lammps found, skipping test")
    else:
        at = get_atoms_with_calc_lammps()
        at.rattle(stdev=0.001, seed=int(time.time()))
        common.makedirs(at.calc.directory)
        print(common.backtick("cp -v utils/lammps/AlN.tersoff {p}/".format(
            p=at.calc.directory)))

        print("scf")
        forces = at.get_forces()
        etot = at.get_potential_energy()
        stress = at.get_stress(voigt=False) # 3x3
        
        st = io.read_lammps_md_txt(at.calc.label + '.out')[0]
        assert np.allclose(forces, st.forces)
        assert np.allclose(etot, st.etot)
        assert np.allclose(st.stress, -stress * constants.eV_by_Ang3_to_GPa,
                           atol=1e-10)
        
        print("relax")
        from ase.optimize import BFGS
        opt = BFGS(at, maxstep=0.04)
        opt.run(fmax=0.001, steps=10)
        coords_frac = parse.arr2d_from_txt("""
            3.3333341909920072e-01    6.6666683819841532e-01    4.4325467247779138e-03
            6.6666681184103216e-01    3.3333362368205072e-01    5.0443254824788963e-01
            3.3333341909918301e-01    6.6666683819838046e-01    3.8356759709402671e-01
            6.6666681184101539e-01    3.3333362368201563e-01    8.8356759861713752e-01
            """)
        assert np.allclose(coords_frac, at.get_scaled_positions(), atol=1e-2)

        # at least 1 backup files must exist
        assert os.path.exists(at.calc.infile + '.0')
        assert os.path.exists(at.calc.outfile + '.0')
        assert os.path.exists(at.calc.dumpfile + '.0')
        assert os.path.exists(at.calc.structfile + '.0')
示例#13
0
def test_lammps_calculator():
    if not have_ase():
        skip("no ASE found, skipping test")
    elif not have_lmp():
        skip("no lammps found, skipping test")
    else:
        at = get_atoms_with_calc_lammps()
        at.rattle(stdev=0.001, seed=int(time.time()))
        common.makedirs(at.calc.directory)
        print common.backtick("cp -v utils/lammps/AlN.tersoff {p}/".format(
            p=at.calc.directory))

        print "scf"
        forces = at.get_forces()
        etot = at.get_potential_energy()
        stress = at.get_stress(voigt=False) # 3x3
        
        st = io.read_lammps_md_txt(at.calc.label + '.out')[0]
        assert np.allclose(forces, st.forces)
        assert np.allclose(etot, st.etot)
        assert np.allclose(st.stress, -stress * constants.eV_by_Ang3_to_GPa,
                           atol=1e-10)
        
        print "relax"
        from ase.optimize import BFGS
        opt = BFGS(at, maxstep=0.04)
        opt.run(fmax=0.001, steps=10)
        coords_frac = parse.arr2d_from_txt("""
            3.3333341909920072e-01    6.6666683819841532e-01    4.4325467247779138e-03
            6.6666681184103216e-01    3.3333362368205072e-01    5.0443254824788963e-01
            3.3333341909918301e-01    6.6666683819838046e-01    3.8356759709402671e-01
            6.6666681184101539e-01    3.3333362368201563e-01    8.8356759861713752e-01
            """)
        assert np.allclose(coords_frac, at.get_scaled_positions(), atol=1e-2)

        # at least 1 backup files must exist
        assert os.path.exists(at.calc.infile + '.0')
        assert os.path.exists(at.calc.outfile + '.0')
        assert os.path.exists(at.calc.dumpfile + '.0')
        assert os.path.exists(at.calc.structfile + '.0')
示例#14
0
def test_plot_dis():
    spp = kpath.SpecialPointsPath(ks=np.array([[0, 0, 0], [.5, 0, 0],
                                               [.7, 0, 0]]),
                                  ks_frac=np.array([[0, 0, 0], [.55, 0, 0],
                                                    [.77, 0, 0]]),
                                  symbols=['A', 'B', 'C'])
    path_norm = np.linspace(0, 1, 100)
    nfreq = 5
    freqs = np.random.rand(100, nfreq)
    try:
        print(os.environ['DISPLAY'])
        fig1, ax1, axdos1 = kpath.plot_dis(path_norm,
                                           freqs,
                                           spp,
                                           show_coords='cart')
        assert axdos1 is None
        fig2, ax2 = mpl.fig_ax()
        kpath.plot_dis(path_norm, freqs, spp, ax=ax2, show_coords='frac')
        lines1 = ax1.get_lines()
        lines2 = ax2.get_lines()
        for idx in range(nfreq):
            x1 = lines1[idx].get_xdata()
            x2 = lines2[idx].get_xdata()
            y1 = lines1[idx].get_ydata()
            y2 = lines2[idx].get_ydata()
            assert (x1 == x2).all()
            assert (y1 == y2).all()
        faxis = np.linspace(freqs.min(), freqs.max(), 30)
        dos = np.array([faxis, np.random.rand(len(faxis))]).T
        fig3, ax3, ax3dos = kpath.plot_dis(path_norm,
                                           freqs,
                                           spp,
                                           dos=dos,
                                           show_coords=None)
        # plot 90 rotated -> x and y swapped
        assert (ax3dos.get_lines()[0].get_xdata() == dos[:, 1]).all()
        assert (ax3dos.get_lines()[0].get_ydata() == dos[:, 0]).all()
    except KeyError:
        tools.skip("no DISPLAY environment variable, skipping test")
示例#15
0
def test_eos():
    # load reference fitted with ElkEOSFit, data points [Bohr^3, Ha] -> [Ang^3, eV]
    # EV input data [Bohr^3, Ry] -> [Ang^3, eV]
    data = np.loadtxt("files/ev/evdata.txt")
    volume = data[:,0] * Bohr3_to_Ang3
    energy = data[:,1] * (Ry / eV)
    ref_ev = np.loadtxt("files/ev/EVPAI.OUT.gz")
    ref_ev[:,0] *= Bohr3_to_Ang3
    ref_ev[:,1] *= (Ha / eV)
    ref_pv = np.loadtxt("files/ev/PVPAI.OUT.gz")
    ref_pv[:,0] *= Bohr3_to_Ang3
    ref_min = np.loadtxt("files/ev/min.txt")
    ref_min[0] *= Bohr3_to_Ang3 # v0
    ref_min[1] *= (Ry / eV)     # e0
    assert ref_ev.shape[0] == ref_pv.shape[0], ("reference data lengths "
        "inconsistent")
    ref = {}        
    ref['ev'] = ref_ev        
    ref['pv'] = ref_pv
    ref['v0'], ref['e0'], ref['p0'], ref['b0'] = ref_min

    # test new EosFit class, default func=Vinet()
    eos = EosFit(volume=volume,
                 energy=energy)
    assert np.allclose(eos.params['v0'], eos.spl.get_min())
    assert np.allclose(eos.params['v0'], eos.get_min())
    assert np.allclose(eos.params['e0'], eos(eos.params['v0']))
    assert np.allclose(eos.params['b0']*eV_by_Ang3_to_GPa, eos.bulkmod(eos.params['v0']))
    now = {}
    now['v0'] = eos.params['v0']
    now['e0'] = eos.params['e0']
    now['b0'] = eos.params['b0'] * eV_by_Ang3_to_GPa
    now['p0'] = eos.pressure(eos.params['v0'])
    for key,val in now.items():
        msg = "EosFit: key=%s, ref=%e, val=%e" %(key, ref[key], val)
        assert np.allclose(val, ref[key], atol=1e-7), msg

    # Test legacy ElkEOSFit / ExternEOS. 
    # 'exe' must be on your $PATH.
    exe = 'eos.x'
    app = common.backtick("which %s" %exe).strip()
    if app == '':
        tools.skip("cannot find '%s' on PATH, skipping test" %exe)
    else:
        eos_store = {}
        type_arr = type(np.array([1.0,2.0]))
        for bv_method in ['ev', 'pv']:
            print("bv_method: %s" %bv_method)
            # natoms = 1, no normalization
            eos = ElkEOSFit(energy=energy,
                            volume=volume,
                            natoms=1,
                            etype=1,
                            npoints=300,
                            dir=testdir,
                            bv_method=bv_method)
            eos.fit()
            now = {}
            now['ev'] = eos.ev
            now['pv'] = eos.pv
            now.update(eos.get_min())
            
            # compare to reference
            for key, val in ref.items():
                print("ElkEOSFit: testing:", key)
                if type(val) == type_arr:
                    np.testing.assert_array_almost_equal(now[key], ref[key])
                else:
                    np.testing.assert_almost_equal(now[key], ref[key],
                                                   decimal=3)
            eos_store[bv_method] = eos
            
            # internal check: are the splines correct?
            for name in ['ev', 'pv', 'bv']:
                # API
                getter = getattr(eos, 'get_spl_' + name)
                assert getattr(eos, 'spl_' + name) == getter()
                # (N,2) arrays self.{ev,pv,bv}
                data = getattr(eos, name)
                vv = data[:,0]
                yy = data[:,1]
                # self.spl_{ev,pv,bv}
                spl = getattr(eos, 'spl_' + name)
                np.testing.assert_array_almost_equal(yy, spl(vv))

        # Other attrs for which we do not have external ref data. Test only
        # among the two bv_methods 'ev' and 'pv'.
        print("bv")
        np.testing.assert_array_almost_equal(eos_store['ev'].bv, 
                                             eos_store['pv'].bv,
                                             decimal=2)
示例#16
0
def test_eos():
    # load reference fitted with ElkEOSFit, data points [Bohr^3, Ha] -> [Ang^3, eV]
    # EV input data [Bohr^3, Ry] -> [Ang^3, eV]
    data = np.loadtxt("files/ev/evdata.txt")
    volume = data[:,0] * Bohr3_to_Ang3
    energy = data[:,1] * (Ry / eV)
    ref_ev = np.loadtxt("files/ev/EVPAI.OUT.gz")
    ref_ev[:,0] *= Bohr3_to_Ang3
    ref_ev[:,1] *= (Ha / eV)
    ref_pv = np.loadtxt("files/ev/PVPAI.OUT.gz")
    ref_pv[:,0] *= Bohr3_to_Ang3
    ref_min = np.loadtxt("files/ev/min.txt")
    ref_min[0] *= Bohr3_to_Ang3 # v0
    ref_min[1] *= (Ry / eV)     # e0
    assert ref_ev.shape[0] == ref_pv.shape[0], ("reference data lengths "
        "inconsistent")
    ref = {}        
    ref['ev'] = ref_ev        
    ref['pv'] = ref_pv
    ref['v0'], ref['e0'], ref['p0'], ref['b0'] = ref_min

    # test new EosFit class, default func=Vinet()
    eos = EosFit(volume=volume,
                 energy=energy)
    assert np.allclose(eos.params['v0'], eos.spl.get_min())
    assert np.allclose(eos.params['v0'], eos.get_min())
    assert np.allclose(eos.params['e0'], eos(eos.params['v0']))
    assert np.allclose(eos.params['b0']*eV_by_Ang3_to_GPa, eos.bulkmod(eos.params['v0']))
    now = {}
    now['v0'] = eos.params['v0']
    now['e0'] = eos.params['e0']
    now['b0'] = eos.params['b0'] * eV_by_Ang3_to_GPa
    now['p0'] = eos.pressure(eos.params['v0'])
    for key,val in now.iteritems():
        msg = "EosFit: key=%s, ref=%e, val=%e" %(key, ref[key], val)
        assert np.allclose(val, ref[key], atol=1e-7), msg

    # Test legacy ElkEOSFit / ExternEOS. 
    # 'exe' must be on your $PATH.
    exe = 'eos.x'
    app = common.backtick("which %s" %exe).strip()
    if app == '':
        tools.skip("cannot find '%s' on PATH, skipping test" %exe)
    else:
        eos_store = {}
        type_arr = type(np.array([1.0,2.0]))
        for bv_method in ['ev', 'pv']:
            print "bv_method: %s" %bv_method
            # natoms = 1, no normalization
            eos = ElkEOSFit(energy=energy,
                            volume=volume,
                            natoms=1,
                            etype=1,
                            npoints=300,
                            dir=testdir,
                            bv_method=bv_method)
            eos.fit()
            now = {}
            now['ev'] = eos.ev
            now['pv'] = eos.pv
            now.update(eos.get_min())
            
            # compare to reference
            for key, val in ref.iteritems():
                print "ElkEOSFit: testing:", key
                if type(val) == type_arr:
                    np.testing.assert_array_almost_equal(now[key], ref[key])
                else:
                    np.testing.assert_almost_equal(now[key], ref[key],
                                                   decimal=3)
            eos_store[bv_method] = eos
            
            # internal check: are the splines correct?
            for name in ['ev', 'pv', 'bv']:
                # API
                getter = getattr(eos, 'get_spl_' + name)
                assert getattr(eos, 'spl_' + name) == getter()
                # (N,2) arrays self.{ev,pv,bv}
                data = getattr(eos, name)
                vv = data[:,0]
                yy = data[:,1]
                # self.spl_{ev,pv,bv}
                spl = getattr(eos, 'spl_' + name)
                np.testing.assert_array_almost_equal(yy, spl(vv))

        # Other attrs for which we do not have external ref data. Test only
        # among the two bv_methods 'ev' and 'pv'.
        print "bv"
        np.testing.assert_array_almost_equal(eos_store['ev'].bv, 
                                             eos_store['pv'].bv,
                                             decimal=2)