Exemple #1
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
Exemple #2
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))
Exemple #3
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
Exemple #4
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
Exemple #5
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)
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)
Exemple #7
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
Exemple #8
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
Exemple #9
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
Exemple #10
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)
Exemple #11
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()
Exemple #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
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
	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}}])
Exemple #15
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
Exemple #16
0
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
import pandas as pd
from glob import glob
from ase.eos import EquationOfState

eos_name = 'birch'

for f in glob('AutoCrossfilts_VASP/*.csv'):
    dat = pd.read_csv(f)
    dat.dropna(inplace=True)
    #if dat:
    print(f)
    try:
        if max(dat['kpts']) > 100000:
            Eos = EquationOfState(dat['volume'], dat['energy'], eos=eos_name)
            E0, E0_err, V0, V0_err, B, B_err, BP, BP_err, y_pred = Eos.fit()
            pd.DataFrame({
                'E0': [E0],
                'V0': [V0],
                'B': [B],
                'BP': [BP]
            }).to_csv('Init_files/{}_Rdata_init.csv'.format(
                f.replace('.csv', '').replace('AutoCrossfilts_VASP/', '')),
                      index=False)
    except:
        print('Issue with {}'.format(f))
Exemple #18
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
Exemple #19
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")

Exemple #20
0
else:

    f = open('volumes_energies.txt', 'rU')

    energies = []
    volumes = []

    lines = f.readlines()

    for i in range(len(lines) - 1):
        volumes.append(float(lines[i + 1].split()[0]))
        energies.append(float(lines[i + 1].split()[1]))
    f.close()

eos = EquationOfState(volumes, energies, eos='birchmurnaghan')
volume, energy, bulkmodulus = eos.fit()
latticeconstant = volume**(1. / 3.)

f = open('log.txt', 'w+')
f.write('lattice constant = {0:18.7f} A\n'.format(latticeconstant))
f.write('bulk energy      = {0:18.7f} eV\n'.format(energy))
f.write('bulk modulus     = {0:18.7f} eV/A^3\n'.format(bulkmodulus))
f.close()

if plot_eos is True:

    eos.plot(show=True)

################################################################################
# END
################################################################################
def test_rescaled_calculator():
    """
    Test rescaled RescaledCalculator() by computing lattice constant
    and bulk modulus using fit to equation of state
    and comparing it to the desired values
    """

    from ase.calculators.eam import EAM
    from ase.units import GPa

    # A simple empirical N-body potential for
    # transition metals by M. W. Finnis & J.E. Sinclair
    # https://www.tandfonline.com/doi/abs/10.1080/01418618408244210
    # using analytical formulation in order to avoid extra file dependence
    # All the constants are taken from the paper.
    # Please refer to the paper for more details

    def pair_potential(r):
        """
        returns the pair potential as a equation 27 in pair_potential
        r - numpy array with the values of distance to compute the pair function
        """
        # parameters for W
        c = 3.25
        c0 = 47.1346499
        c1 = -33.7665655
        c2 = 6.2541999

        energy = (c0 + c1 * r + c2 * r**2.0) * (r - c)**2.0
        energy[r > c] = 0.0

        return energy

    def cohesive_potential(r):
        """
        returns the cohesive potential as a equation 28 in pair_potential
        r - numpy array with the values of distance to compute the pair function
        """
        # parameters for W
        d = 4.400224

        rho = (r - d)**2.0
        rho[r > d] = 0.0

        return rho

    def embedding_function(rho):
        """
        returns energy as a function of electronic density from eq 3
        """

        A = 1.896373
        energy = -A * np.sqrt(rho)

        return energy

    cutoff = 4.400224
    W_FS = EAM(elements=['W'],
               embedded_energy=np.array([embedding_function]),
               electron_density=np.array([[cohesive_potential]]),
               phi=np.array([[pair_potential]]),
               cutoff=cutoff,
               form='fs')

    # 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.calc = calc
        v = at.get_volume()
        e = at.get_potential_energy()
        return v, e

    # desired DFT values
    a0_qm = 3.18556
    C11_qm = 522  # pm 15 GPa
    C12_qm = 193  # pm 5 GPa
    B_qm = (C11_qm + 2.0 * C12_qm) / 3.0

    bulk_at = bulk("W", cubic=True)

    mm_calc = W_FS
    eps = np.linspace(-0.01, 0.01, 13)
    v_mm, E_mm = zip(*[strain(bulk_at, e, mm_calc) for e in eps])

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

    mm_r = RescaledCalculator(mm_calc, a0_qm, B_qm, a0_mm, B_mm)
    bulk_at = bulk("W", cubic=True, a=a0_qm)
    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()
    B_mm_r /= GPa
    a0_mm_r = v0_mm_r**(1.0 / 3)

    # check match of a0 and B after rescaling is adequate
    # 0.1% error in lattice constant and bulk modulus
    assert abs((a0_mm_r - a0_qm) / a0_qm) < 1e-3
    assert abs((B_mm_r - B_qm) / B_qm) < 1e-3
Exemple #22
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
assert abs((a0_mm_r - a0_qm) / a0_qm) < 1e-3  # 0.1% error in lattice constant
Exemple #23
0
def lattice_constant(volumes, energies):
    eos = EquationOfState(volumes, energies)
    v, e, B = eos.fit()
    a = (v * 4)**(1 / 3)
    return a
Exemple #24
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()
Exemple #25
0
    print 'a0 %f\n'% (opt_cell[0][0])

    # reoptimize/check volume
    #
    volumes = []
    energies = []
    for x in np.linspace(0.98, 1.02, 5):
        bulk.set_cell(opt_cell * x, scale_atoms=True)
        volumes.append(bulk.get_volume() / bulk.get_number_of_atoms())
        energies.append(bulk.get_potential_energy() / bulk.get_number_of_atoms())

    # fit EOS
    #
    eos = EquationOfState(volumes, energies)
    vpaf, epaf, B1 = eos.fit()
    print "EOS vpaf:", vpaf, "A^3"
    print "EOS epaf:", epaf, "eV"
    print "EOS B1:", B1 / kJ * 1.0e24, "GPa"

    strain = 0.001
    diag = ([1, 0, 0],
            [0, 1, 0],
            [0, 0, 1])

    # c44
    #
    defm1 = np.array([[0, strain, strain],
                  [strain, 0, strain],
                  [strain, strain, 0]])
    cell1 = np.dot(opt_cell, defm1 + diag)
Exemple #26
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
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))
Exemple #28
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))
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))
Exemple #30
0
from ase.io.trajectory import Trajectory
from ase.io import read
from ase.units import kJ
from ase.eos import EquationOfState, vinet

numberline = 0
f3 = open('e-v.dat')
for line in f3:
    numberline = numberline + 1

energies = np.zeros(numberline)
volumes = np.zeros(numberline)
i = 0
with open("e-v.dat") as f3:
    for line in f3:
        line = line.rstrip('\n')
        volumes[i], energies[i] = line.split(" ")
        i = i + 1

eos = EquationOfState(volumes, energies, eos='vinet')
eos.fit()
e0, B, Bp, v0 = eos.eos_parameters
fp = open("helmholtz-volume.dat")
for i, line in enumerate(fp):
    if i == 1:
        a, b, Fmin, d, e, V = line.split()
fp.close()
print(float(Fmin) - vinet(float(V), e0, B, Bp, v0)),
#print eos
#v0, e0, B= eos.fit()
def main():

    latoms = vf.get_list_of_atoms()
    latoms2 = vf.get_list_of_outcar()

    natoms = latoms[0].get_positions().shape[0]

    V = np.array([]) 
    ca = np.array([])
    magtot = np.array([])

    for i in np.arange(len(latoms)):
        temp = latoms[i].get_volume()/natoms
        V = np.append(V, temp) 
        
        temp = latoms[i].get_cell()[:]
        temp = np.linalg.norm( temp[2,:] ) / np.linalg.norm( temp[0,:] ) 
        ca = np.append(ca, temp) 


        try:
            temp = latoms2[i].get_magnetic_moment()/natoms
        except:
            temp = 0
        magtot = np.append(magtot, temp)
        
    magtot = np.abs(magtot)


    jobn, Etot, Eent, pres = vf.vasp_read_post_data()

    a_pos = np.array([])  # scale in POSCAR
    for i in jobn:
        filename = './y_dir/%s/CONTCAR' %(i)
        with open(filename,'r') as f:
            a_pos = np.append( a_pos, float( f.readlines()[1] ) )

 
    Etot = Etot / natoms
    fitres = myfitting(V, Etot)


    V1 = np.array([])
    a1_pos = np.array([])
    p_dft = np.array([])

    for i in np.arange(len(jobn)):
        p_dft = np.append( p_dft, pres[i,0:2].mean()*(0.1) )  # pressure [GPa]
        
        if jobn[i][0] == '0' or jobn[i][0] == '1' :   
            V1 = np.append( V1, V[i] / float(jobn[i]))
            a1_pos = np.append( a1_pos, a_pos[i] / (float(jobn[i]))**(1/3) )
     
    
    if (V1.std() > 1e-8) or (a1_pos.std() > 1e-8) :
        print('V1, V1.std(), a1_pos.std():')
        print( V1, V1.std(), a1_pos.std()  )
        sys.exit('V1 or a1_pos is wrong. Abort!')
    else:
        V1 = V1.mean()
        a1_pos = a1_pos.mean()

    write_output(V, Etot, fitres, V1, a1_pos, p_dft)
    plot_eos(V, Etot, fitres, p_dft, V1, ca, magtot)


    ASE_eos = EquationOfState(V, Etot, eos='birchmurnaghan')
    temp = np.array([ 
    ASE_eos.fit()[1] - fitres[0], 
    ASE_eos.fit()[0] - fitres[1],
    ASE_eos.fit()[2] - fitres[2] ])
    print('==> check with ASE fitting, diff: {0} \n'.format(temp) )
Exemple #32
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')
Exemple #33
0
def test_forceqmmm():
    # parameters
    N_cell = 2
    R_QMs = np.array([3, 7])

    # setup bulk and MM region
    bulk_at = bulk("Cu", cubic=True)
    sigma = (bulk_at * 2).get_distance(0, 1) * (2.**(-1. / 6))
    mm = LennardJones(sigma=sigma, epsilon=0.05)
    qm = EMT()

    # 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.calc = 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
    assert abs(
        (a0_mm_r - a0_qm) / a0_qm) < 1e-3  # 0.1% error in lattice constant
    assert abs((B_mm_r - B_qm) / B_qm) < 0.05  # 5% error in bulk modulus

    # plt.plot(v_mm, E_mm - np.min(E_mm), 'o-', label='MM')
    # plt.plot(v_qm, E_qm - np.min(E_qm), 'o-', label='QM')
    # plt.plot(v_mm_r, E_mm_r - np.min(E_mm_r), 'o-', label='MM rescaled')
    # plt.legend()

    at0 = bulk_at * N_cell
    r = at0.get_distances(0, np.arange(1, len(at0)), mic=True)
    print(len(r))
    del at0[0]  # introduce a vacancy
    print("N_cell", N_cell, 'N_MM', len(at0))

    ref_at = at0.copy()
    ref_at.calc = qm
    opt = FIRE(ref_at)
    opt.run(fmax=1e-3)
    u_ref = ref_at.positions - at0.positions

    us = []
    for R_QM in R_QMs:
        at = at0.copy()
        mask = r < R_QM
        print('R_QM', R_QM, 'N_QM', mask.sum(), 'N_total', len(at))
        qmmm = ForceQMMM(at, mask, qm, mm, buffer_width=2 * qm.rc)
        at.calc = qmmm
        opt = FIRE(at)
        opt.run(fmax=1e-3)
        us.append(at.positions - at0.positions)

    # compute error in energy norm |\nabla u - \nabla u_ref|
    def strain_error(at0, u_ref, u, cutoff, mask):
        I, J = neighbor_list('ij', at0, cutoff)
        I, J = np.array([(i, j) for i, j in zip(I, J) if mask[i]]).T
        v = u_ref - u
        dv = np.linalg.norm(v[I, :] - v[J, :], axis=1)
        return np.linalg.norm(dv)

    du_global = [
        strain_error(at0, u_ref, u, 1.5 * sigma, np.ones(len(r))) for u in us
    ]
    du_local = [strain_error(at0, u_ref, u, 1.5 * sigma, r < 3.0) for u in us]

    print('du_local', du_local)
    print('du_global', du_global)

    # check local errors are monotonically decreasing
    assert np.all(np.diff(du_local) < 0)

    # check global errors are monotonically converging
    assert np.all(np.diff(du_global) < 0)

    # biggest QM/MM should match QM result
    assert du_local[-1] < 1e-10
    assert du_global[-1] < 1e-10
Exemple #34
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.")
Exemple #35
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