示例#1
0
def test_eos():
    import numpy as np
    import scipy  # skip test early if no scipy
    from ase.build import bulk
    from ase.calculators.emt import EMT
    from ase.eos import EquationOfState as EOS, eos_names
    scipy  # silence pyflakes

    b = bulk('Al', 'fcc', a=4.0, orthorhombic=True)
    b.set_calculator(EMT())
    cell = b.get_cell()

    volumes = []
    energies = []
    for x in np.linspace(0.98, 1.01, 5):
        b.set_cell(cell * x, scale_atoms=True)
        volumes.append(b.get_volume())
        energies.append(b.get_potential_energy())

    results = []
    for name in eos_names:
        if name == 'antonschmidt':
            # Someone should fix this!
            continue
        eos = EOS(volumes, energies, name)
        v, e, b = eos.fit()
        print('{0:20} {1:.8f} {2:.8f} {3:.8f} '.format(name, v, e, b))
        assert abs(v - 3.18658700e+01) < 4e-4
        assert abs(e - -9.76187802e-03) < 5e-7
        assert abs(b - 2.46812688e-01) < 2e-4
        results.append((v, e, b))

    print(np.ptp(results, 0))
    print(np.mean(results, 0))
示例#2
0
def calc_lattice_parameter_al(atom_set, A, lmbd, D, mu2):
    global n_sets, cells
    q = 0.2
    n_points = 10
    lattice_param_set = np.zeros(n_sets)
    calc = get_calc((A, lmbd, D, mu2))

    for index, atoms in enumerate(atom_set):
        # # # Find lattice constant with lowest energy # # #
        cell_0 = atoms.cells[index]  # Unit cell object of the Al bulk
        atoms.set_calculator(calc)
        energies = []
        volumes = []
        inval = np.linspace(-q, q, n_points)
        for eps in inval:

            atoms.cell = (1 + eps) * cell_0  # Adjust lattice constant of unit cell

            # Calculate the potential energy for the Al bulk
            energies.append(atoms.get_potential_energy())
            volumes.append(atoms.get_volume())

        # Plot energies as a function of unit cell volume (directly related to latt. const.)
        eos = EquationOfState(volumes, energies)
        v0, E, B = eos.fit()
        # Latt. const. acc. to ASE doc., but why is this correct?
        a_calc = v0**(1 / 3.0)

        n_min = np.argmin(energies)
        atoms.cell = (1 + inval[n_min]) * cell_0
        lattice_param_set[index] = a_calc
    return lattice_param_set
示例#3
0
    def eos(self, atoms, name):
        args = self.args

        traj = Trajectory(self.get_filename(name, 'traj'), 'w', atoms)

        N, eps = args.equation_of_state.split(',')
        N = int(N)
        eps = float(eps) / 100
        strains = np.linspace(1 - eps, 1 + eps, N)
        v1 = atoms.get_volume()
        volumes = strains**3 * v1
        energies = []
        cell1 = atoms.cell
        for s in strains:
            atoms.set_cell(cell1 * s, scale_atoms=True)
            energies.append(atoms.get_potential_energy())
            traj.write(atoms)
        traj.close()
        eos = EquationOfState(volumes, energies, args.eos_type)
        v0, e0, B = eos.fit()
        atoms.set_cell(cell1 * (v0 / v1)**(1 / 3), scale_atoms=True)
        data = {'volumes': volumes,
                'energies': energies,
                'fitted_energy': e0,
                'fitted_volume': v0,
                'bulk_modulus': B,
                'eos_type': args.eos_type}
        return data
def fit(filename):
    configs = read(filename + "@:")
    volumes = [a.get_volume() for a in configs]
    energies = [a.get_potential_energy() for a in configs]
    eos = EquationOfState(volumes, energies)
    v0, e0, B = eos.fit()
    return (4 * v0)**(1 / 3.0)
示例#5
0
    def eos(self, atoms, name):
        args = self.args

        traj = Trajectory(self.get_filename(name, 'traj'), 'w', atoms)

        N, eps = args.equation_of_state.split(',')
        N = int(N)
        eps = float(eps) / 100
        strains = np.linspace(1 - eps, 1 + eps, N)
        v1 = atoms.get_volume()
        volumes = strains**3 * v1
        energies = []
        cell1 = atoms.cell
        for s in strains:
            atoms.set_cell(cell1 * s, scale_atoms=True)
            energies.append(atoms.get_potential_energy())
            traj.write(atoms)
        traj.close()
        eos = EquationOfState(volumes, energies, args.eos_type)
        v0, e0, B = eos.fit()
        atoms.set_cell(cell1 * (v0 / v1)**(1 / 3), scale_atoms=True)
        data = {
            'volumes': volumes,
            'energies': energies,
            'fitted_energy': e0,
            'fitted_volume': v0,
            'bulk_modulus': B,
            'eos_type': args.eos_type
        }
        return data
示例#6
0
    def eos(self, atoms, name):
        args = self.args

        traj = Trajectory(self.get_filename(name, 'traj'), 'w', atoms)

        N, eps = args.equation_of_state.split(',')
        N = int(N)
        eps = float(eps) / 100
        strains = np.linspace(1 - eps, 1 + eps, N)
        v1 = atoms.get_volume()
        volumes = strains**3 * v1
        energies = []
        cell1 = atoms.cell
        for s in strains:
            atoms.set_cell(cell1 * s, scale_atoms=True)
            energies.append(atoms.get_potential_energy())
            traj.write(atoms)
        traj.close()
        eos = EquationOfState(volumes, energies, args.eos_type)
        v0, e0, B = eos.fit()
        atoms.set_cell(cell1 * (v0 / v1)**(1 / 3), scale_atoms=True)
        from ase.parallel import parprint as p
        p('volumes:', volumes)
        p('energies:', energies)
        p('fitted energy:', e0)
        p('fitted volume:', v0)
        p('bulk modulus:', B)
        p('eos type:', args.eos_type)
示例#7
0
def calc_lattice_parameter(al_bulk_ASE, A, lmbd, D, mu2):
    q = 0.2
    n_points = 15
    calc = get_calc((A, lmbd, D, mu2))

    # # # Find lattice constant with lowest energy # # #
    cell_0 = al_bulk_ASE.get_cell()  # Unit cell object of the Al bulk
    al_bulk_ASE.set_calculator(calc)
    energies = []
    volumes = []

    for eps in np.linspace(-q, q, n_points):

        al_bulk_ASE.set_cell(
            (1 + eps) * cell_0)  # Adjust lattice constant of unit cell

        # Calculate the potential energy for the Al bulk
        energies.append(al_bulk_ASE.get_potential_energy())
        volumes.append(al_bulk_ASE.get_volume())

    #plt.plot(np.asarray(volumes)**(1 / 3), energies)
    # plt.show()
    # Plot energies as a function of unit cell volume (directly related to latt. const.)
    eos = EquationOfState(volumes, energies)
    v0, E, B = eos.fit()
    # Latt. const. acc. to ASE doc., but why is this correct?
    a_calc = v0**(1 / 3.0)
    print('a=' + str(a_calc))

    al_bulk_ASE.set_cell(cell_0)

    return a_calc
示例#8
0
def eosfit_spec(atoms, calc, rg, method="birchmurnaghan"):
    from ase.eos import EquationOfState
    from numpy import linspace
    rootdir = os.getcwd()
    if not os.path.exists('eosfit'):
        os.mkdir('eosfit')
    os.chdir('eosfit')
    cell = atoms.get_cell()
    atoms.set_calculator(calc)
    traj = Trajectory('eosfit.traj', 'w')
    for x in rg:
        print(str(x))
        atoms.set_cell(cell * x, scale_atoms=True)
        atoms.get_potential_energy()
        traj.write(atoms)
    configs = Trajectory('eosfit.traj', 'r')
    volumes = [at.get_volume() for at in configs]
    energies = [at.get_potential_energy() for at in configs]
    eos = EquationOfState(volumes, energies, eos=method)
    v0, e0, B = eos.fit()
    eos.plot('eosfit.svg')
    fp = open('eosdata.dat', 'w')
    fp.write('Volume\t\tEnergy')
    for i in range(len(configs)):
        fp.write(str(volumes[i]) + '\t' + str(energies[i]) + '\n')
    os.chdir(rootdir)
示例#9
0
def calc_lattice_parameter_al(al_bulk, A, lmbd, D, mu2):
    q = 0.03
    n_points = 14
    calc = get_calc((A, lmbd, D, mu2))
    # # # Find lattice constant with lowest energy # # #
    cell_0 = al_bulk.cell  # Unit cell object of the Al bulk
    al_bulk.set_calculator(calc)
    energies = []
    volumes = []

    for eps in np.linspace(-q, q, n_points):

        al_bulk.cell = (1 + eps) * cell_0  # Adjust lattice constant of unit cell

        # Calculate the potential energy for the Al bulk
        energies.append(al_bulk.get_potential_energy())
        volumes.append(al_bulk.get_volume())

    # Plot energies as a function of unit cell volume (directly related to latt. const.)
    eos = EquationOfState(volumes, energies)
    v0, E, B = eos.fit()
    # Latt. const. acc. to ASE doc., but why is this correct?
    a_calc = (4 * v0)**(1 / 3.0)
    al_bulk.cell = cell_0

    print('Lattice_parameter:', a_calc)
    return a_calc
示例#10
0
    def do_autotune_volume(self,start_scan=0.90,end_scan=1.10,num_scan=25,exclude_type=None,only_type=None):

        # Load system and calculator
        system = self.system.copy()
        calc = self.system.calc 
        system.set_calculator(calc)
        # Scale volumes and collect energy & volume measurements
        ens = []
        vols = []
        start_cell = system.get_cell()
        
        print("Performing volume scan.")
        for i,x in enumerate(np.linspace(start_scan,end_scan,num_scan)):
            #print(i)
            scale = x**(1./3.)
            system.set_cell(scale*start_cell,scale_atoms=True)
            vols.append(system.get_volume())
            ens.append(system.get_potential_energy())
        self.volume_vs_energy = [vols,ens]
            
        # Fit to Equations of States
        print("Fitting data to equations of state.")
        eos_types = "sjeos taylor murnaghan birch birchmurnaghan pouriertarantola p3 antonschmidt".split()
        if exclude_type != None:
            _ = [eos_types.remove(i) for i in exclude_type]
        elif only_type != None:
            eos_types = only_type
            
        eos_fits = {}
        errors = []
        
        for typ in eos_types:
            try:
                eos = EquationOfState(vols,ens,eos=typ)
                v, e, B = eos.fit()
                eos_fits[typ] = {'volume':v,'energy':e,'buld_modulus':B}
            except:
                errors.append(typ)

        self.eos_fits = eos_fits
        self.eos_errors = errors if len(errors)>0 else None

        if len(errors) > 0:
            print("WARNING: Was not able to fit equation of state for the following: {}".format(errors))
        # Rescale initial cell to optimized volume
        print("Rescaling with optimized volume.")
        vol_avg = np.average([eos_fits[key]['volume'] for key in eos_fits.keys()])
        system.set_cell(start_cell,scale_atoms=True)
        scale = (vol_avg/system.get_volume())**(1./3.)
        print("Optimized volume: {}".format(vol_avg))
        del self.system
        self.system = system
        self.system.set_cell(scale*start_cell,scale_atoms=True)
        
        print("Performing second relaxation.")
        self.system.get_potential_energy()
示例#11
0
def fit(symbol: str) -> Tuple[float, float, float, float]:
    V = []
    E = []
    for atoms in read('{}.traj@:'.format(symbol)):
        V.append(atoms.get_volume() / len(atoms))
        E.append(atoms.get_potential_energy() / len(atoms))
    eos = EOS(V, E, 'birchmurnaghan')
    eos.fit()
    e0, B, Bp, v0 = eos.eos_parameters
    return e0, v0, B, Bp
示例#12
0
def relax(input_atoms, ref_db):
    atoms_string = input_atoms.get_chemical_symbols()

    # Open connection to the database with reference data
    db = connect(ref_db)

    # Load our model structure which is just FCC
    atoms = FaceCenteredCubic('X', latticeconstant=1.)
    atoms.set_chemical_symbols(atoms_string)

    # Compute the average lattice constant of the metals in this individual
    # and the sum of energies of the constituent metals in the fcc lattice
    # we will need this for calculating the heat of formation
    a = 0
    ei = 0
    for m in set(atoms_string):
        dct = db.get(metal=m)
        count = atoms_string.count(m)
        a += count * dct.latticeconstant
        ei += count * dct.energy_per_atom
    a /= len(atoms_string)
    atoms.set_cell([a, a, a], scale_atoms=True)

    # Since calculations are extremely fast with EMT we can also do a volume
    # relaxation
    atoms.set_calculator(EMT())
    eps = 0.05
    volumes = (a * np.linspace(1 - eps, 1 + eps, 9))**3
    energies = []
    for v in volumes:
        atoms.set_cell([v**(1. / 3)] * 3, scale_atoms=True)
        energies.append(atoms.get_potential_energy())

    eos = EquationOfState(volumes, energies)
    v1, ef, B = eos.fit()
    latticeconstant = v1**(1. / 3)

    # Calculate the heat of formation by subtracting ef with ei
    hof = (ef - ei) / len(atoms)

    # Place the calculated parameters in the info dictionary of the
    # input_atoms object
    input_atoms.info['key_value_pairs']['hof'] = hof
    
    # Raw score must always be set
    # Use one of the following two; they are equivalent
    input_atoms.info['key_value_pairs']['raw_score'] = -hof
    # set_raw_score(input_atoms, -hof)
    
    input_atoms.info['key_value_pairs']['latticeconstant'] = latticeconstant

    # Setting the atoms_string directly for easier analysis
    atoms_string = ''.join(input_atoms.get_chemical_symbols())
    input_atoms.info['key_value_pairs']['atoms_string'] = atoms_string
示例#13
0
def relax(input_atoms, ref_db):
    atoms_string = input_atoms.get_chemical_symbols()

    # Open connection to the database with reference data
    db = connect(ref_db)

    # Load our model structure which is just FCC
    atoms = FaceCenteredCubic('X', latticeconstant=1.)
    atoms.set_chemical_symbols(atoms_string)

    # Compute the average lattice constant of the metals in this individual
    # and the sum of energies of the constituent metals in the fcc lattice
    # we will need this for calculating the heat of formation
    a = 0
    ei = 0
    for m in set(atoms_string):
        dct = db.get(metal=m)
        count = atoms_string.count(m)
        a += count * dct.latticeconstant
        ei += count * dct.energy_per_atom
    a /= len(atoms_string)
    atoms.set_cell([a, a, a], scale_atoms=True)

    # Since calculations are extremely fast with EMT we can also do a volume
    # relaxation
    atoms.set_calculator(EMT())
    eps = 0.05
    volumes = (a * np.linspace(1 - eps, 1 + eps, 9))**3
    energies = []
    for v in volumes:
        atoms.set_cell([v**(1. / 3)] * 3, scale_atoms=True)
        energies.append(atoms.get_potential_energy())

    eos = EquationOfState(volumes, energies)
    v1, ef, B = eos.fit()
    latticeconstant = v1**(1. / 3)

    # Calculate the heat of formation by subtracting ef with ei
    hof = (ef - ei) / len(atoms)

    # Place the calculated parameters in the info dictionary of the
    # input_atoms object
    input_atoms.info['key_value_pairs']['hof'] = hof

    # Raw score must always be set
    # Use one of the following two; they are equivalent
    input_atoms.info['key_value_pairs']['raw_score'] = -hof
    # set_raw_score(input_atoms, -hof)

    input_atoms.info['key_value_pairs']['latticeconstant'] = latticeconstant

    # Setting the atoms_string directly for easier analysis
    atoms_string = ''.join(input_atoms.get_chemical_symbols())
    input_atoms.info['key_value_pairs']['atoms_string'] = atoms_string
示例#14
0
文件: gui.py 项目: ssrokyz/ase-3.20.1
 def bulk_modulus(self):
     try:
         v = [abs(np.linalg.det(atoms.cell)) for atoms in self.images]
         e = [self.images.get_energy(a) for a in self.images]
         from ase.eos import EquationOfState
         eos = EquationOfState(v, e)
         plotdata = eos.getplotdata()
     except Exception as err:
         self.bad_plot(err, _('Images must have energies '
                              'and varying cell.'))
     else:
         self.pipe('eos', plotdata)
示例#15
0
	def run_task(self,fw_spec): 
		
		jobID,latticeParams = fw_spec['jobID'],fw_spec['latticeParams'] # WHY IS LATTICEPARAMS [[FLOAT]] INSTEAD OF [FLOAT]?
		job   = db2object(jobID)

		existsPrecalc 	= job.precalc != 'None'
		optAtoms  		= job.fromParams(latticeParams[0]) 
		optCell   		= optAtoms.get_cell()
		strains   		= np.linspace(1-job.strain,1+job.strain,9)
		calc      		= job.calc(restart=True) if existsPrecalc else job.calc()
		
		vol,eng = [],[]
		
		for i, strain in enumerate(strains):
			atoms = optAtoms.copy()
			atoms.set_cell(optCell*strain,scale_atoms=True)

			if existsPrecalc: 
				preCalc = job.calc(precalc=True)
				job.optimizePos(atoms,preCalc,saveWF = True)
				if job.dftcode =='gpaw': 
					atoms,calc = job.gpawRestart()

			job.optimizePos(atoms,calc)

			energy = atoms.get_potential_energy()
			volume = atoms.get_volume()
			vol.append(deepcopy(volume))
			eng.append(deepcopy(energy))
			parprint('%f %f'%(strain,energy))
			with paropen('bulkmod.log','a') as logfile: 
				logfile.write('%s\t%s\n' %(strain,energy))
				parprint('%f %f'%(strain,energy))

		aHat,quadR2 = quadFit(np.array(deepcopy(vol)),np.array(deepcopy(eng)))

		try:		
			eos = EquationOfState(vol,eng)
			v0, e0, b = eos.fit()
			eos.plot(filename='bulk-eos.png',show=False)
			b0= b/kJ*1e24 #GPa use this value if EOS doesn't fail
		except ValueError:  # too bad of a fit for ASE to handle
			b0 = aHat*2*vol[4]*160.2 # units: eV/A^6 * A^3 * 1, where 1 === 160.2 GPa*A^3/eV

		return FWAction( stored_data=        {'b0':b0,'quadR2':quadR2}
						,mod_spec=[{'_push': {'b0':b0,'quadR2':quadR2}}])
示例#16
0
def Free_energy(
    x, T, E0, V0, B0, Bp
):  #T in K, M is molar mass, E0 in eV, V0 in A^3, B0 in eV/A^3, x is concentration in atomic fraction
    try:
        i = 0
        M = 0
        for el in elements:
            M = M + mass_dict[el] * x[i]
            i = i + 1
        M = abs(M)
        r0 = (3 * V0 / 4 / np.pi)**(1.0 / 3.0)
        T_D0 = C * np.sqrt(r0 * B0 * 160.21766208 / M)
        g = 1 - (np.tanh(4 * (T - T_D0) / T_D0) / 2.0 +
                 0.5) / 3.0  #2/3 for high T, 1 for low T
        gamma = -g + 0.5 * (1 + Bp)
        x = np.array(x)
        V = np.linspace(V0 - 0.1 * V0, V0 + 0.1 * V0, NUM_VOL_POINTS)
        F_temp = []
        for Vi in V:
            E = E0 + 9 * V0 * B0 / 16 * (((V0 / Vi)**(2.0 / 3.0) - 1)**3 * Bp +
                                         ((V0 / Vi)**(2.0 / 3.0) - 1)**2 *
                                         (6 - 4 * (V0 / Vi)**(2.0 / 3.0)))
            T_D = T_D0 * (V0 / Vi)**gamma
            x = T_D / T
            #t = np.linspace(0.000001,x,10000)
            #Deb_func = 3.0 / x**3 * np.trapz(t**3 / (np.exp(t) - 1), t)
            F_vib = 9.0 / 8.0 * kB * T_D - kB * T * Debye(
                x) + 3 * kB * T * np.log(1 - np.exp(-(T_D / T)))
            F = E + F_vib
            F_temp.append(F)
        eos = EquationOfState(V, F_temp)
        vol_eq, F_eq, B_eq = eos.fit()
        return F_eq
    except KeyboardInterrupt:
        raise
    except Exception as e:
        print(x)
        raise
示例#17
0
文件: xtb_ev.py 项目: egh17/TightEV
def ev_bulk(volumes, energies, plot_name):
    """Plot volume energy curve and calculates bulk modulus

    Args:
        volumes (list of float): The volumes correlated to the energies calculated.
        energies (list of float): The energies the cell calculated by gfn0 xtb.
        plot_name (str): The file name the plot is saved to. 

    Returns:
        v0 (float): The volume of minimum energy.
        e0 (float): The fitted minimum energy of the V/E curve.
        B (float): The calculated bulk modulus. 

    """
    volumes = np.array(volumes)
    energies = np.array(energies) * Hartree / eV
    eos = EquationOfState(volumes, energies, eos="murnaghan")
    v0, e0, B = eos.fit()
    print(B / kJ * 1.0e24, "GPa")  # Converts into GPa
    ax = eos.plot()
    fig = plt.gcf()
    fig.set_size_inches(8, 5)
    fig.savefig(plot_name)
    return v0, e0, B
示例#18
0
# compute MM and QM equations of state
def strain(at, e, calc):
    at = at.copy()
    at.set_cell((1.0 + e) * at.cell, scale_atoms=True)
    at.set_calculator(calc)
    v = at.get_volume()
    e = at.get_potential_energy()
    return v, e


eps = np.linspace(-0.01, 0.01, 13)
v_qm, E_qm = zip(*[strain(bulk_at, e, qm) for e in eps])
v_mm, E_mm = zip(*[strain(bulk_at, e, mm) for e in eps])

eos_qm = EquationOfState(v_qm, E_qm)
v0_qm, E0_qm, B_qm = eos_qm.fit()
a0_qm = v0_qm**(1.0 / 3.0)

eos_mm = EquationOfState(v_mm, E_mm)
v0_mm, E0_mm, B_mm = eos_mm.fit()
a0_mm = v0_mm**(1.0 / 3.0)

mm_r = RescaledCalculator(mm, a0_qm, B_qm, a0_mm, B_mm)
v_mm_r, E_mm_r = zip(*[strain(bulk_at, e, mm_r) for e in eps])

eos_mm_r = EquationOfState(v_mm_r, E_mm_r)
v0_mm_r, E0_mm_r, B_mm_r = eos_mm_r.fit()
a0_mm_r = v0_mm_r**(1.0 / 3)

# check match of a0 and B after rescaling is adequete
示例#19
0
from ase.calculators.emt import EMT
from ase.eos import EquationOfState
from ase.db import connect

db = connect('refs.db')

metals = ['Al', 'Au', 'Cu', 'Ag', 'Pd', 'Pt', 'Ni']
for m in metals:
    atoms = FaceCenteredCubic(m)
    atoms.calc = EMT()
    e0 = atoms.get_potential_energy()
    a = atoms.cell[0][0]

    eps = 0.05
    volumes = (a * np.linspace(1 - eps, 1 + eps, 9))**3
    energies = []
    for v in volumes:
        atoms.set_cell([v**(1. / 3)] * 3, scale_atoms=True)
        energies.append(atoms.get_potential_energy())

    eos = EquationOfState(volumes, energies)
    v1, e1, B = eos.fit()

    atoms.set_cell([v1**(1. / 3)] * 3, scale_atoms=True)
    ef = atoms.get_potential_energy()

    db.write(atoms,
             metal=m,
             latticeconstant=v1**(1. / 3),
             energy_per_atom=ef / len(atoms))
示例#20
0
"""

cell = bulk.get_cell()
traj = Trajectory('bulk.traj', 'w')
for x in np.linspace(0.90, 1.10, 5):
    bulk.set_cell(cell * x, scale_atoms=True)
    bulk.get_potential_energy()
    traj.write(bulk)

########## EOS #############

from ase.io import read
from ase.units import kJ
from ase.eos import EquationOfState
configs = read('bulk.traj@0:5')  # read 10 configurations
# Extract volumes and energies:
volumes = [bulk.get_volume() for bulk in configs]
energies = [bulk.get_potential_energy() for bulk in configs]
eos = EquationOfState(volumes, energies, eos='birchmurnaghan')
v0, e0, B = eos.fit()

# Return info on optimised system
print("Volume: ", v0 + " Angstrom^3")
print("Total energy at a0: " + e0 + " eV")
print("FCC Lattice parameter a0: ", (4*v0)**(1/3), "Angstrom")
#print("FCC Lattice parameter a0: ", (4*v0/NUMBER_OF_ATOMS_IN_UNIT_CELL)**(1/3), "Angstrom")
print("Bulk modulus: ", B / kJ * 1.0e24, 'GPa')
eos.plot('bulk-eos.png')

#view('bulk.traj')
示例#21
0
from ase.calculators.emt import EMT
from ase.eos import EquationOfState as EOS, eos_names
scipy  # silence pyflakes

b = bulk('Al', 'fcc', a=4.0, orthorhombic=True)
b.set_calculator(EMT())
cell = b.get_cell()

volumes = []
energies = []
for x in np.linspace(0.98, 1.01, 5):
    b.set_cell(cell * x, scale_atoms=True)
    volumes.append(b.get_volume())
    energies.append(b.get_potential_energy())

results = []
for name in eos_names:
    if name == 'antonschmidt':
        # Someone should fix this!
        continue
    eos = EOS(volumes, energies, name)
    v, e, b = eos.fit()
    print('{0:20} {1:.8f} {2:.8f} {3:.8f} '.format(name, v, e, b))
    assert abs(v - 3.18658700e+01) < 4e-4
    assert abs(e - -9.76187802e-03) < 5e-7
    assert abs(b - 2.46812688e-01) < 2e-4
    results.append((v, e, b))

print(np.ptp(results, 0))
print(np.mean(results, 0))
示例#22
0
def fit_a(conv, n, description_for_archive, analysis_type, show, push2archive):
    """Fit equation of state for bulk systems.

    The following equation is used::

       sjeos (default)
           A third order inverse polynomial fit 10.1103/PhysRevB.67.026103

                           2      3        -1/3
       E(V) = c + c t + c t  + c t ,  t = V
               0   1     2      3

       taylor
           A third order Taylor series expansion about the minimum volume

       murnaghan
           PRB 28, 5480 (1983)

       birch
           Intermetallic compounds: Principles and Practice,
           Vol I: Principles. pages 195-210

       birchmurnaghan
           PRB 70, 224107

       pouriertarantola
           PRB 70, 224107

       vinet
           PRB 70, 224107

       antonschmidt
           Intermetallics 11, 23-32 (2003)

       p3
           A third order polynomial fit

        Use::

           eos = EquationOfState(volumes, energies, eos='sjeos')
           v0, e0, B = eos.fit()
           eos.plot()

    """
    # e, v, emin, vmin       = plot_conv( conv[n], calc,  "fit_gb_volume2")

    alist = []
    vlist = []
    etotlist = []
    magn1 = []
    magn2 = []
    alphas = []
    for id in conv[n]:
        cl = db[id]
        st = cl.end
        alist.append(cl.end.rprimd[0][0])
        etotlist.append(cl.energy_sigma0)
        vlist.append(cl.end.vol)
        magn1.append(cl.magn1)
        magn2.append(cl.magn2)
        alpha, beta, gamma = st.get_angles()
        alphas.append(alpha)
        print('alpha, energy: {:4.2f}, {:6.3f}'.format(alpha,
                                                       cl.energy_sigma0))

    fit_and_plot(U1=(alphas, etotlist, 'o-r'),
                 image_name='figs/angle',
                 ylabel='Total energy, eV',
                 xlabel='Angle, deg',
                 xlim=(89, 92.6))

    if ase_flag:
        if 'angle' in analysis_type:
            eos = EquationOfState(alphas, etotlist, eos='sjeos')
        else:
            eos = EquationOfState(vlist, etotlist, eos='sjeos')
        # import inspect

        # print (inspect.getfile(EquationOfState))

        v0, e0, B = eos.fit()
        #print "c = ", clist[2]
        printlog('''
        v0 = {0} A^3
        a0 = {1} A
        E0 = {2} eV
        B  = {3} eV/A^3'''.format(v0, v0**(1. / 3), e0, B),
                 imp='Y')

        savedpath = 'figs/' + cl.name + '.png'
        makedir(savedpath)

        cl.B = B * 160.218
        # plt.close()
        # plt.clf()
        # plt.close('all')
        if 'fit' in show:
            mpl.rcParams.update({'font.size': 14})

            eos.plot(savedpath, show=True)
            printlog('fit results are saved in ', savedpath, imp='y')
        else:
            printlog('To use fitting install ase: pip install ase')
    # plt.clf()

    if push2archive:
        push_figure_to_archive(local_figure_path=savedpath,
                               caption=description_for_archive)

    return
示例#23
0
            cell_0 = al.cell  # Unit cell object of the Al bulk
            for eps in np.linspace(-0.02, 0.02, N_lattice_spacings):
                al.cell = (
                    1 + eps) * cell_0  # Adjust lattice constant of unit cell
                # Calculate the potential energy for the Al bulk
                energies.append(al.get_potential_energy())
                volumes.append(al.get_volume())

            #
            # confs = read('out.txt@0:' + str(N_lattice_spacings))  # Read the configurations
            # # Extract volumes and energies:
            # volumes = [atoms.get_volume() for atoms in confs]
            # energies = [atoms.get_potential_energy() for atoms in confs]
            # # if rank == 0:
            # #     print energies, shape(energies)
            #
            if rank == 0:
                print 'Energies: ' + str(energies)
                print 'Volumes: ' + str(volumes)
                # Plot energies as a function of unit cell volume (directly related to latt. const.)
                eos = EquationOfState(volumes, energies)
                v0, E_bulk, B = eos.fit()
                eos.plot('Al_eos.png')
                # Latt. const. acc. to ASE doc., but why is this correct?
                a_calc = (4 * v0)**(1 / 3.0)

                print 'a_calc: ' + str(a_calc)

        else:
            al.get_potential_energy()
示例#24
0
def calc_lattice_parameter(al_bulk_ASE, A, lmbd, D, mu2):
    calc = get_calc((A, lmbd, D, mu2))
    eps = 0.001
    energies = []
    volumes = []
    al_bulk_ASE.set_calculator(calc)

    # # # Find lattice constant with lowest energy # # #
    cell_0 = al_bulk_ASE.get_cell()  # Unit cell object of the Al bulk

    # DIRECTION
    cell_orig = cell_0

    E1 = al_bulk_ASE.get_potential_energy()
    al_bulk_ASE.set_cell((1 + eps) * cell_0)
    E2 = al_bulk_ASE.get_potential_energy()

    direction = (E2 - E1) / abs((E2 - E1))
    print('Direction', direction)

    # Go one step in the right
    al_bulk_ASE.set_cell(cell_orig)
    energies.append(al_bulk_ASE.get_potential_energy())
    volumes.append(al_bulk_ASE.get_volume())

    cell_0 = al_bulk_ASE.get_cell()

    al_bulk_ASE.set_cell(
        (1 - direction * eps) * cell_0)  # Adjust lattice constant of unit cell

    energies.append(al_bulk_ASE.get_potential_energy())
    volumes.append(al_bulk_ASE.get_volume())

    # Go two steps back
    while (energies[-1] - energies[-2]) < 0:
        cell_0 = al_bulk_ASE.get_cell()
        # Adjust lattice constant of unit cell
        al_bulk_ASE.set_cell((1 - direction * eps) * cell_0)

        # Calculate the potential energy for the Al bulk
        energies.append(al_bulk_ASE.get_potential_energy())
        volumes.append(al_bulk_ASE.get_volume())

    cell_0 = al_bulk_ASE.get_cell()
    al_bulk_ASE.set_cell(
        (1 - direction * eps) * cell_0)  # Adjust lattice constant of unit cell

    # Calculate the potential energy for the Al bulk
    energies.append(al_bulk_ASE.get_potential_energy())
    volumes.append(al_bulk_ASE.get_volume())
    # plt.plot((4 * np.asarray(volumes))**(1 / 3), energies)
    # plt.show()
    # Plot energies as a function of unit cell volume (directly related to latt. const.)
    eos = EquationOfState(volumes, energies)
    v0, E, B = eos.fit()
    # Latt. const. acc. to ASE doc., but why is this correct?
    print('asdasdasdasdasd: ', E)
    a_calc = (4 * v0)**(1 / 3.0)
    # a_calc = v0**(1 / 3.0)
    print('a=' + str(a_calc))

    al_bulk_ASE.set_cell(cell_0)

    return a_calc
示例#25
0
    INP_FILELIST.append(pwinput.filename)
    pwinput.write()

# run commands
OUT_FILELIST = []
for i, f in enumerate(INP_FILELIST):
    fileout = "OUT_PW_" + str(i)
    OUT_FILELIST.append(fileout)
    # Uncomment this if the run is already done
    os.system("pw.x < " + f + " > " + fileout)
    print("Running " + str(i) + " is done")

ene = np.zeros(len(OUT_FILELIST))
for i, f in enumerate(OUT_FILELIST):
    ene[i] = read_pwscf_energy(f)
    print("ene[i] = ", ene[i])

from ase.units import Bohr, kJ
from ase.eos import EquationOfState

volumes = A_LIST[:]**3 / 4.0  # fcc volumes (in Angstrom^3)
ene[:] = ene[:] * Ry  # convert to eV

eos = EquationOfState(volumes, ene)
v0, e0, B = eos.fit()
print("B = %18.10f GPa" % (B / kJ * 1.0e24))
eos.plot("IMG_fit_EOS.pdf")

a_calc = (4 * v0)**(1 / 3)
print("a_exp  = ", a_exp)
print("a_calc = ", a_calc)
示例#26
0
from ase.io import read
from ase.units import kJ
from ase.eos import EquationOfState
configs = read('Ag.traj@0:5')  # read 5 configurations
# Extract volumes and energies:
volumes = [ag.get_volume() for ag in configs]
energies = [ag.get_potential_energy() for ag in configs]
eos = EquationOfState(volumes, energies)
v0, e0, B = eos.fit()
print(B / kJ * 1.0e24, 'GPa')
eos.plot('Ag-eos.png')
示例#27
0
energies = []
volumes = []
LC = [3.5, 3.55, 3.6, 3.65, 3.7, 3.75]

for a in LC:
    cu_bulk = bulk("Cu", "fcc", a=a)

    calc = EMT()

    cu_bulk.set_calculator(calc)

    e = cu_bulk.get_potential_energy()
    energies.append(e)
    volumes.append(cu_bulk.get_volume())

eos = EquationOfState(volumes, energies)
v0, e0, B = eos.fit()
aref = 3.6
vref = bulk("Cu", "fcc", a=aref).get_volume()

copper_lattice_constant = (v0 / vref)**(1 / 3) * aref

slab = fcc100("Cu", a=copper_lattice_constant, size=(2, 2, 3))
ads = molecule("C")
add_adsorbate(slab, ads, 3, offset=(1, 1))
cons = FixAtoms(indices=[atom.index for atom in slab if (atom.tag == 3)])
slab.set_constraint(cons)
slab.center(vacuum=13.0, axis=2)
slab.set_pbc(True)
slab.wrap(pbc=[True] * 3)
slab.set_calculator(copy.copy(parent_calc))
示例#28
0

def genstr(scale):
    atoms = read('str.cif')

    # Scale the cell
    cell = atoms.get_cell()
    cell[2][2] = scale * cell[2][2]
    atoms.set_cell(cell, scale_atoms=False)

    # Translate Li, F atoms vertically
    for j in range(len(atoms)):
        if atoms[j].symbol != 'C':
            atoms[j].position[2] += (scale - 1) * 11.08 / 2
    return atoms


# Main
for i, scale in enumerate(np.linspace(0.85, 1.0, num=5)):
    atoms = genstr(scale)
    atoms.calc = GPAW(xc=xc, kpts=kpoints, gpts=gpoints, txt=str(i) + '.txt')
    e.append(atoms.get_potential_energy())
    v.append(atoms.get_volume())

eos = EquationOfState(v, e, eos='birchmurnaghan')
v0, e0, B = eos.fit()
eos.plot('eos.png', show=False)
opt_scale = v0 / read('str.cif').get_volume()

write('opt_str.cif', genstr(opt_scale))
示例#29
0
def getBulkModulus(jobID, latticeParams):
    """
	Use optimized lattice parameters from fmin(getEnergy). Calculate energies around the minimum. 
	Returns optimized atomic positions, energy of minimum, calculated bulk modulus, and writes wavefunctions to file inp.gpw
	"""
    ### INITIALIZE
    vol, eng = [], []
    jobObject, bulkObject, calcObject, dft, preCalcObject, preCalcObject, existsPrecalc, optAtoms, magmoms = initialize(
        jobID, latticeParams)
    with open('lattice_opt.log', 'r') as f:
        nIter = len(f.readlines()) + 9  #count number of ionic steps taken
    optCell = optAtoms.get_cell()
    strains = np.linspace(0.99, 1.01, 9)

    ### GENERATE dE/dV plot
    for i, strain in enumerate(strains):
        atoms = deepcopy(optAtoms)
        atoms.set_cell(optCell * strain, scale_atoms=True)
        ### PRECALCULATE
        if existsPrecalc:
            optimizePos(atoms,
                        dft,
                        preCalcObject,
                        magmoms,
                        restart=False,
                        saveWF=True)
        ### CALCULATE
        optimizePos(atoms,
                    dft,
                    calcObject,
                    magmoms,
                    restart=existsPrecalc,
                    saveWF=False)
        ### COLLECT RESULTS
        energy = atoms.get_potential_energy()
        volume = atoms.get_volume()
        vol.append(deepcopy(volume))
        eng.append(deepcopy(energy))
        parprint('%f %f' % (strain, energy))
        ### COLLECT DETAILED DATA ABOUT MINIMUM ENERGY STATE
        if i == 4:
            pos = atoms.get_scaled_positions()
            vMin = deepcopy(volume)
            io.write('optimized.traj', atoms)
            magmom = atoms.get_magnetic_moments(
            ) if calcObject.magmom > 0 else np.zeros(len(atoms))
            if dft == 'gpaw':
                atoms.calc.write('inp.gpw',
                                 mode='all')  #for use in getXCContribs

    aHat, quadR2 = quadFit(np.array(deepcopy(vol)), np.array(deepcopy(eng)))
    b0 = aHat * 2 * vMin * 160.2  # units: eV/A^6 * A^3 * 1, where 1 === 160.2 GPa*A^3/eV
    parprint('quadR2 = ' + str(quadR2))
    try:
        eos = EquationOfState(vol, eng)
        v0, e0, b = eos.fit()
        eos.plot(filename='bulk-eos.png', show=False)
        b0 = b / kJ * 1e24  #GPa use this value if EOS doesn't fail
    except ValueError:
        e0 = eng[4]
    return (optCell, nIter, pos, magmom, e0, b0, quadR2)  #GPa
示例#30
0
文件: plot_a.py 项目: thonmaker/gpaw
def lattice_constant(volumes, energies):
    eos = EquationOfState(volumes, energies)
    v, e, B = eos.fit()
    a = (v * 4)**(1 / 3)
    return a
示例#31
0
    def do_volume_autotune(self,
                           encut=None,
                           start_scan=0.925,
                           end_scan=1.075,
                           num_scans=20,
                           exclude_type=None,
                           only_type=None):
        if not os.path.isfile(self.poscar_vol):
            encut = encut if encut != None else self.do_encut_autotune()

            logging.info("Commencing volume scan...")
            print("Determining optimal volume...")
            start_scan, end_scan, num_scans, exclude_type, only_type, vols, ens = self.set_volume_autotune_params(
                start_scan=start_scan,
                end_scan=end_scan,
                num_scans=num_scans,
                exclude_type=exclude_type,
                only_type=only_type)

            # Load POSCAR
            try:
                sys = read(self.poscar_init)
                calc = self.calc_dict['volume']
                calc.set(encut=encut)
                start_cell = sys.get_cell()
            except:
                logging.error(
                    "Initial POSCAR file could not be found at {}".format(
                        poscar_init))
                print("Error: See error log for details.")
                return None
            logging.info("Loaded initial POSCAR file.")

            # Do volume scan
            logging.info("Performing volume scan.")
            for x in np.linspace(start_scan, end_scan, num_scans):
                sys.set_cell(x * start_cell, scale_atoms=True)
                sys.set_calculator(calc)
                ens.append(sys.get_potential_energy())
                vols.append(sys.get_volume())
            logging.info("Volume scan complete.")

            # Fit EoS
            logging.info("Fitting equations of state.")
            eos_types = "sjeos taylor murnaghan birch birchmurnaghan pouriertarantola p3 antonschmidt".split(
            )

            if exclude_type != None:
                _ = [eos_types.remove(i) for i in exclude]
            elif only_type != None:
                eos_types = only_type

            eos_fits = {}
            for typ in eos_types:
                eos = EquationOfState(vols, ens, eos=typ)
                try:
                    v, e, B = eos.fit()
                    eos_fits[typ] = {
                        'volume': v,
                        'energy': e,
                        'buld_modulus': B
                    }
                except:
                    print("Unable to fit type {}.".format(typ))

            # Rescale initial cell to optimized volume
            logging.info("Optimal volume found. Rescaling original cell.")
            vol_avg = np.average(
                [eos_fits[key]['volume'] for key in eos_fits.keys()])
            sys.set_cell(start_cell, scale_atoms=True)

            scale = sys.get_volume() / vol_avg
            sys.set_cell(scale * start_cell, scale_atoms=True)

            # Perform sc-step
            logging.info("Performing self-consistent step.")
            print("Second relaxation")
            #calc.set(isif=3)  # Everything can relax
            sys.set_calculator(calc)
            en = sys.get_potential_energy()

            # Set relaxed structure as active structure
            print("Setting relaxed structure to active structure.")
            self.system = sys

            # Save structure
            logging.info("Saving self-consistent calculator.")
            write(self.poscar_vol, sys)

            print("Done.")
            logging.info("Volume scan complete.")
            self.clean_up()
        else:
            sys = read(self.poscar_vol)
            print("Volume optimized system ready.")
示例#32
0
from ase.units import kJ, Bohr, Hartree
from ase.eos import EquationOfState
import numpy as np

filename = "TEMP_EOS_data.dat"
dat = np.loadtxt(filename)

# dont forget to convert to Angstrom and eV
volumes = dat[:,0]**3/2.0 * Bohr**3  # only for bcc
energies = dat[:,1]*Hartree
energies_abinit = dat[:,2]*Hartree
energies_pwscf  = dat[:,3]*Hartree

eos = EquationOfState(volumes, energies)
v0, e0, B = eos.fit()
print("PWDFT.jl: B = %18.10f GPa" % (B/kJ * 1.0e24))
eos.plot("pwdft-eos-ase.pdf")

eos = EquationOfState(volumes, energies_abinit)
v0, e0, B = eos.fit()
print("ABINIT  : B = %18.10f GPa" % (B/kJ * 1.0e24))
eos.plot("abinit-eos-ase.pdf")

eos = EquationOfState(volumes, energies_pwscf)
v0, e0, B = eos.fit()
print("PWSCF   : B = %18.10f GPa" % (B/kJ * 1.0e24))
eos.plot("pwscf-eos-ase.pdf")

示例#33
0
import numpy as np

from ase.lattice.cubic import FaceCenteredCubic
from ase.calculators.emt import EMT
from ase.eos import EquationOfState
from ase.db import connect

db = connect("refs.db")

metals = ["Al", "Au", "Cu", "Ag", "Pd", "Pt", "Ni"]
for m in metals:
    atoms = FaceCenteredCubic(m)
    atoms.set_calculator(EMT())
    e0 = atoms.get_potential_energy()
    a = atoms.cell[0][0]

    eps = 0.05
    volumes = (a * np.linspace(1 - eps, 1 + eps, 9)) ** 3
    energies = []
    for v in volumes:
        atoms.set_cell([v ** (1.0 / 3)] * 3, scale_atoms=True)
        energies.append(atoms.get_potential_energy())

    eos = EquationOfState(volumes, energies)
    v1, e1, B = eos.fit()

    atoms.set_cell([v1 ** (1.0 / 3)] * 3, scale_atoms=True)
    ef = atoms.get_potential_energy()

    db.write(atoms, metal=m, latticeconstant=v1 ** (1.0 / 3), energy_per_atom=ef / len(atoms))
示例#34
0
文件: eos.py 项目: nan-1212/postqe
 def __init__(self, volumes, energies, eos='sj'):
     EquationOfState.__init__(self, volumes, energies, eos='sj')