def analyse(self): for name, data in self.data.items(): if 'strains' in data: atoms = self.create_system(name) # use relaxed volume if present if 'relaxed volume' in data: volume = data['relaxed volume'] else: volume = atoms.get_volume() volumes = data['strains']**3 * volume energies = data['energies'] # allow selection of eos type independent of data if self.eos is not None: eos = EquationOfState(volumes, energies, self.eos) else: eos = EquationOfState(volumes, energies) try: v, e, B = eos.fit() except (RuntimeError, ValueError): pass else: data['fitted energy'] = e data['volume'] = v data['B'] = B if abs(v) < min(volumes) or abs(v) > max(volumes): raise ValueError(name + ': fit outside of range! ' + \ str(abs(v)) + ' not in ' + \ str(volumes))
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)
def bulk_summary(self, plot, a0): natoms = len(self.atoms) eos = EquationOfState(self.volumes, self.energies) v, e, B = eos.fit() x = (v / self.atoms.get_volume())**(1.0 / 3) self.log('Fit using %d points:' % len(self.energies)) self.log('Volume per atom: %.3f Ang^3' % (v / natoms)) if a0: a = a0 * x self.log('Lattice constant: %.3f Ang' % a) else: a = None self.log('Bulk modulus: %.1f GPa' % (B * 1e24 / units.kJ)) self.log('Total energy: %.3f eV (%d atom%s)' % (e, natoms, ' s'[1:natoms])) if plot: import pylab as plt plt.plot(self.volumes, self.energies, 'o') x = np.linspace(self.volumes[0], self.volumes[-1], 50) plt.plot(x, eos.fit0(x**-(1.0 / 3)), '-r') plt.show() bulk = self.atoms.copy() bulk.set_cell(x * bulk.cell, scale_atoms=True) self.write_optimized(bulk, e) return e, v, B, a
def eos(self, atoms, name): opts = self.opts traj = PickleTrajectory(self.get_filename(name, 'traj'), 'w', atoms) eps = 0.01 strains = np.linspace(1 - eps, 1 + eps, 5) 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, opts.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': opts.eos_type} return data
def f(width, k, g): filename = 'Fe-FD-%.2f-%02d-%2d.traj' % (width, k, g) configs = read(filename + '@::2') # Extract volumes and energies: 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 v0, e0, B
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 input_atoms.info['key_value_pairs']['raw_score'] = -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 analyse(self): for name, data in self.data.items(): if 'strains' in data: atoms = self.create_system(name) volumes = data['strains']**3 * atoms.get_volume() energies = data['energies'] eos = EquationOfState(volumes, energies) try: v, e, B = eos.fit() except ValueError: pass else: data['fitted energy'] = e data['volume'] = v data['B'] = B
def analyse(self): OptimizeTask.analyse(self) for name, data in self.data.items(): if 'strains' in data: atoms = self.create_system(name) volumes = data['strains']**3 * atoms.get_volume() energies = data['energies'] eos = EquationOfState(volumes, energies) try: v, e, B = eos.fit() except ValueError: self.results[name].extend([None, None]) else: self.results[name][1:] = [energies[2] - e, v, B * 1e24 / units.kJ] else: self.results[name].extend([None, None])
def test_calculator(): """ Take ASE structure, PySCF object, and run through ASE calculator interface. This allows other ASE methods to be used with PySCF; here we try to compute an equation of state. """ ase_atom=Diamond(symbol='C', latticeconstant=3.5668) # Set up a cell; everything except atom; the ASE calculator will # set the atom variable cell = pbcgto.Cell() cell.h=ase_atom.cell cell.basis = 'gth-szv' cell.pseudo = 'gth-pade' cell.gs=np.array([8,8,8]) cell.verbose = 0 # Set up the kind of calculation to be done # Additional variables for mf_class are passed through mf_dict mf_class=pbcdft.RKS mf_dict = { 'xc' : 'lda,vwn' } # Once this is setup, ASE is used for everything from this point on ase_atom.set_calculator(pyscf_ase.PySCF(molcell=cell, mf_class=mf_class, mf_dict=mf_dict)) print "ASE energy", ase_atom.get_potential_energy() print "ASE energy (should avoid re-evaluation)", ase_atom.get_potential_energy() # Compute equation of state ase_cell=ase_atom.cell volumes = [] energies = [] for x in np.linspace(0.95, 1.2, 5): ase_atom.set_cell(ase_cell * x, scale_atoms = True) print "[x: %f, E: %f]" % (x, ase_atom.get_potential_energy()) volumes.append(ase_atom.get_volume()) energies.append(ase_atom.get_potential_energy()) eos = EquationOfState(volumes, energies) v0, e0, B = eos.fit() print(B / kJ * 1.0e24, 'GPa') eos.plot('eos.png')
def analyse(self): for name, data in self.data.items(): if 'strains' in data: atoms = self.create_system(name) volumes = data['strains']**3 * atoms.get_volume() energies = data['energies'] eos = EquationOfState(volumes, energies) try: v, e, B = eos.fit() except ValueError: pass else: data['fitted energy'] = e data['volume'] = v data['B'] = B if abs(v) < min(volumes) or abs(v) > max(volumes): raise ValueError(name + ': fit outside of range! ' + \ str(abs(v)) + ' not in ' + \ str(volumes))
def eosanal(volumes,energies,CI): eos=EquationOfState(volumes,energies) #Performs the EOS calcs v0,e0,B0=eos.fit() #Gives us the values at minimum energy def func(x): #sets up the function to be solved return CI-erf(.701707*x) #Proposes the function dictating the normal random variable z=fsolve(func,0) #solves for the normal random variable v=np.power(volumes,-.3333333) #sets up the variable as the one in the EOS fit3=np.polyder(((np.poly1d(np.polyfit(v,energies,3)))),2) #Creates an equation that solves for the bulk modulus in the same manner as the EOS BM=fit3(v)/9*v**5 #solves for the bulk modulus corresponding to each volume value var=[np.std(volumes),np.std(energies),np.std(BM)] #solves for the standard deviation of each set of data of interest SS=[np.count_nonzero(volumes),np.count_nonzero(energies),np.count_nonzero(BM)] #determines the sample size of each set of data of interest. R=[z*var[0]*SS[0]**-.5,z*var[1]*SS[1]**-.5,z*var[2]*SS[2]**-.5] #Determines the radius of the confidence interval Limits=[v0-R[0],v0+R[0],e0-R[1],e0+R[1],B0-R[2],B0+R[2]] #sets up each confidence interval print 'The {0} confidence interval around the volume at minimum energy of the selected structure is between {1} and {2} A^3.The {0} confidence interval around the minimum energy of the selected structure is between {3} and {4} eV.The {0} confidence interval around the bulk modulus of the selected structure is between {5} and {6} eV/A^3 '.format(CI,Limits[0],Limits[1],Limits[2],Limits[3],Limits[4],Limits[5]) #displays the results return;
from ase.calculators.emt import EMT from ase.utils.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. / 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))
e = atoms.get_potential_energy() energies.append(e) ones.append(1) except (VaspSubmitted, VaspQueued): ready = False if not ready: import sys sys.exit() for m in LC: with jasp("bulk/Cl-{0}".format(m)) as calc: atoms = calc.get_atoms() volumes.append(atoms.get_volume()) eos = EquationOfState(volumes, energies) v0, e0, B0 = eos.fit() CI = 0.95 def func(x): return CI - erf(0.701707 * x) z = fsolve(func, 0) v = np.power(volumes, -0.3333333) fit3 = np.polyder(((np.poly1d(np.polyfit(v, energies, 3)))), 2) BM = fit3(v) / 9 * v ** 5 var = [np.std(volumes), np.std(energies), np.std(BM)] SS = [np.count_nonzero(volumes), np.count_nonzero(energies), np.count_nonzero(BM)] R = [z * var[0] * SS[0] ** -0.5, z * var[1] * SS[1] ** -0.5, z * var[2] * SS[2] ** -0.5]
from vasp import Vasp from ase.utils.eos import EquationOfState LC = [3.5, 3.55, 3.6, 3.65, 3.7, 3.75] energies = [] volumes = [] for a in LC: calc = Vasp('bulk/Cu-{0}'.format(a)) atoms = calc.get_atoms() volumes.append(atoms.get_volume()) energies.append(atoms.get_potential_energy()) calc.stop_if(None in energies) eos = EquationOfState(volumes, energies) v0, e0, B = eos.fit() print ''' v0 = {0} A^3 E0 = {1} eV B = {2} eV/A^3'''.format(v0, e0, B) eos.plot('images/Cu-fcc-eos.png')
v = atoms.get_volume() volumes.append(v) f.write('{0:1.3f} {1:1.5f} {2:1.5f}'.format(a, v, e)) except: print('aims failed when a = {0:1.3f}'.format(a)) ready = False if not ready: import sys; sys.exit() print '#+tblname: pt-bcc-latt' print r'| lattice constant ($\AA$) | Total Energy (eV) |' for lc, e in zip(LC, energies): print '| {0} | {1} |'.format(lc, e) import matplotlib.pyplot as plt plt.plot(LC, energies) plt.xlabel('Lattice constant ($\AA$)') plt.ylabel('Total energy (eV)') plt.savefig('images/pt-bcc-latt.png') eos = EquationOfState(volumes, energies) v0, e0, B = eos.fit() print ''' v0 = {0} A^3 E0 = {1} eV B = {2} eV/A^3'''.format(v0, e0, B) f.write('v0 = {0} A^3 \n E0 = {1} eV \n B = {2} eV/A^3'.format(v0, e0, B)) eos.plot('images/pt-bcc-eos.png') f.close()
def analyse(self, atomsfile=None): try: BulkTask.analyse(self) except ValueError: # allow fit outside of range pass for name, data in self.data.items(): if 'strains' in data: atoms = self.create_system(name) # use relaxed volume if present if 'relaxed volume' in data: volume = data['relaxed volume'] else: volume = atoms.get_volume() volumes = data['strains']**3 * volume energies = data['energies'] # allow selection of eos type independent of data if self.eos is not None: eos = EquationOfState(volumes, energies, self.eos) else: eos = EquationOfState(volumes, energies) try: v, e, B = eos.fit() except ValueError: pass else: data['fitted energy'] = e data['volume'] = v data['B'] = B # with respect tot the reference volume data['volume error [%]'] = (data['volume'] / atoms.get_volume() - 1) * 100 if self.collection.B: i = self.collection.labels.index(self.collection.xc) - 1 B = self.collection.B[name][i] * units.kJ * 1e-24 data['B error [%]'] = (data['B'] / B - 1) * 100 else: data['B error [%]'] = None data['strukturbericht'] = self.collection.data[name][0] data['crystal structure'] = strukturbericht[data['strukturbericht']] # calculate lattice constant from volume cs = data['crystal structure'] if cs == 'bcc': a0 = (volume*2)**(1/3.) a = (data['volume']*2)**(1/3.) elif cs == 'cesiumchloride': a0 = (volume)**(1/3.) a = (data['volume'])**(1/3.) elif cs in ['fcc', 'diamond', 'zincblende', 'rocksalt', 'fluorite']: a0 = (volume*4)**(1/3.) a = (data['volume']*4)**(1/3.) i = self.collection.labels.index(self.collection.xc) - 1 a0_ref = self.collection.data[name][i] if 'relaxed volume' not in data: # no volume relaxation performed - volume equals the reference one assert abs(a0 - a0_ref) < 1.e-4 data['lattice constant'] = a data['lattice constant error [%]'] = (a - a0_ref) / a0_ref * 100 if atomsfile: # MDTMP: TODO atomdata = read_json(atomsfile) for name, data in self.data.items(): atoms = self.create_system(name) e = -data['energy'] for atom in atoms: e += atomdata[atom.symbol]['energy'] e /= len(atoms) data['cohesive energy'] = e if self.collection.xc == 'PBE': eref = self.collection.data[name][7] else: eref = self.collection.data[name][9] data['cohesive energy error [%]'] = (e / eref - 1) * 100 self.summary_keys += ['cohesive energy', 'cohesive energy error [%]']
cell.basis = 'gth-szv' cell.pseudo = 'gth-pade' cell.verbose = 0 # Set up the kind of calculation to be done # Additional variables for mf_class are passed through mf_dict mf_class = pbcdft.RKS mf_dict = {'xc': 'lda,vwn'} # Once this is setup, ASE is used for everything from this point on ase_atom.set_calculator( pyscf_ase.PySCF(molcell=cell, mf_class=mf_class, mf_dict=mf_dict)) print("ASE energy", ase_atom.get_potential_energy()) print("ASE energy (should avoid re-evaluation)", ase_atom.get_potential_energy()) # Compute equation of state ase_cell = ase_atom.cell volumes = [] energies = [] for x in np.linspace(0.95, 1.2, 5): ase_atom.set_cell(ase_cell * x, scale_atoms=True) print "[x: %f, E: %f]" % (x, ase_atom.get_potential_energy()) volumes.append(ase_atom.get_volume()) energies.append(ase_atom.get_potential_energy()) eos = EquationOfState(volumes, energies) v0, e0, B = eos.fit() print(B / kJ * 1.0e24, 'GPa') eos.plot('eos.png')
from jasp import * from ase.utils.eos import EquationOfState LC = [3.5, 3.55, 3.6, 3.65, 3.7, 3.75] energies = [] volumes = [] for a in LC: with jasp('bulk/Cu-{0}'.format(a)) as calc: atoms = calc.get_atoms() volumes.append(atoms.get_volume()) energies.append(atoms.get_potential_energy()) eos = EquationOfState(volumes, energies) v0, e0, B = eos.fit() print ''' v0 = {0} A^3 E0 = {1} eV B = {2} eV/A^3'''.format(v0, e0, B) eos.plot('images/Cu-fcc-eos.png')
xc='PBE', encut=350, kpts=(6,6,6), isym=2, atoms=newatoms) calculators.append(calc) # now we set up the Pool of processes pool = multiprocessing.Pool(processes=NCORES) # get the output from running each calculation out = pool.map(do_calculation, calculators) pool.close() pool.join() # this makes the script wait here until all jobs are done # now proceed with analysis V = [x[0] for x in out] E = [x[1] for x in out] eos = EquationOfState(V, E) v1, e1, B = eos.fit() print 'step1: v1 = {v1}'.format(**locals()) ### ################################################################ ## STEP 2, eos around the minimum ## ################################################################# factors = [-0.06, -0.04, -0.02, 0.0, 0.02, 0.04, 0.06] calculators = [] # reset list for f in factors: newatoms = atoms.copy() newatoms.set_volume(v1*(1 + f)) label = 'bulk/cu-mp/step2-{0}'.format(COUNTER) COUNTER += 1 calc = jasp(label,
from __future__ import print_function import pickle import numpy as np import matplotlib.pyplot as plt from ase.utils.eos import EquationOfState import ase.units as units results = [] K = range(3, 13) for k in K: A, data = pickle.load(open('eos-%d.pckl' % k)) for energies, xcname in zip(data, ['PBE', 'LDA', 'PBE0']): eos = EquationOfState(A**3 / 4, energies) v0, e0, B = eos.fit() a = (v0 * 4)**(1 / 3.0) B *= 1.0e24 / units.kJ print(('%-4s %2d %.3f %.3f %.2f' % (xcname, k, a, e0, B))) results.append((a, B)) results = np.array(results).reshape((-1, 3, 2)) LDA = dict(a=5.4037, B=95.1, eGX=0.52) PBE = dict( a=5.469, B=87.8, eGG=2.56, eGX=0.71, eGL=1.54, eI=0.47, # indirect ea=4.556) PBE0 = dict(a=5.433, B=99.0, eGG=3.96, eGX=1.93, eGL=2.87, eI=1.74, ea=4.555)
def get_e_v(fname): data = np.loadtxt(fname, usecols=(1, 3, 5, 6, 7)) volumes = data[:, 1] energies = data[:, 4] return volumes, energies def custom_plot(volumes, energies, eos): plot.plot(volumes, energies, 'ro') x = np.linspace(min(eos.v), max(eos.v), 100) y = eval(eos.eos_string)(x, eos.eos_parameters[0], eos.eos_parameters[1], eos.eos_parameters[2], eos.eos_parameters[3]) plot.plot(x, y, label='fit') plot.xlabel('Volume ($\AA^3$)') plot.ylabel('Energy (eV)') plot.legend(loc='best') plot.savefig('eos.png') plot.show() if __name__ == '__main__': volumes, energies = get_e_v('test_bulk.txt') # eos = 'sjeos', 'murnaghan', 'birch', 'taylor', 'vinet' etc. eos = EquationOfState(volumes, energies, eos='murnaghan') v0, e0, B = eos.fit() # the ASE units for the bulk modulus is eV/Angstrom^3 print('optimum volume, energy and bulk moduls', v0, e0, B) # plot # eos.plot(filename= "eos_fit") custom_plot(volumes, energies, eos)
# reoptimize/check volume # volumes = [] energies = [] for x in np.linspace(0.98, 1.02, 5): atoms.set_cell(init_cell * x, scale_atoms=True) volumes.append(atoms.get_volume() / atoms.get_number_of_atoms()) energies.append(atoms.get_potential_energy() / atoms.get_number_of_atoms()) print "per atom volumes:", volumes print "per atom energies:", energies # fit EOS # from ase.utils.eos import EquationOfState eos = EquationOfState(volumes, energies) vpaf, epaf, B1 = eos.fit() print "vpaf:", vpaf, "A^3" print "epaf:", epaf, "eV" print "B1:", B1 / kJ * 1.0e24, "GPa" # get optimal lattice parameter from optimal volume # volrc = abs(np.linalg.det(refcell)) optlp = pow(vpaf * atoms.get_number_of_atoms() / volrc, 1. / 3.) print "optlp:", optlp, "\n" # get actual energy at optimal volume # opt_cell = optlp * refcell atoms.set_cell(opt_cell, scale_atoms=True)
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") from picture_functions import fit_and_plot 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
try: e=atoms.get_potential_energy() energies.append(e) ones.append(1) except (VaspSubmitted,VaspQueued): ready=False if not ready: import sys; sys.exit() for m in LC: with jasp('bulk/Cl-{0}'.format(m)) as calc: atoms=calc.get_atoms() volumes.append(atoms.get_volume()) # all of the above sets up the problem for the code below. It simply creates an FCC Cl. Changing the above can easily make a different structure. print volumes print energies eos=EquationOfState(volumes,energies) #Performs the EOS calcs v0,e0,B0=eos.fit() #Gives us the values at minimum energy CI=.95 #Determines the level of Confidence Interval def func(x): #sets up the function to be solved return CI-erf(.701707*x) #Proposes the function dictating the normal random variable z=fsolve(func,0) #solves for the normal random variable v=np.power(volumes,-.3333333) #sets up the variable as the one in the EOS fit3=np.polyder(((np.poly1d(np.polyfit(v,energies,3)))),2) #Creates an equation that solves for the bulk modulus in the same manner as the EOS BM=fit3(v)/9*v**5 #solves for the bulk modulus corresponding to each volume value var=[np.std(volumes),np.std(energies),np.std(BM)] #solves for the standard deviation of each set of data of interest SS=[np.count_nonzero(volumes),np.count_nonzero(energies),np.count_nonzero(BM)] #determines the sample size of each set of data of interest. R=[z*var[0]*SS[0]**-.5,z*var[1]*SS[1]**-.5,z*var[2]*SS[2]**-.5] #Determines the radius of the confidence interval Limits=[v0-R[0],v0+R[0],e0-R[1],e0+R[1],B0-R[2],B0+R[2]] #sets up each confidence interval print 'The {0} confidence interval around the volume at minimum energy of the selected structure is between {1} and {2} A^3.The {0} confidence interval around the minimum energy of the selected structure is between {3} and {4} eV.The {0} confidence interval around the bulk modulus of the selected structure is between {5} and {6} eV/A^3 '.format(CI,Limits[0],Limits[1],Limits[2],Limits[3],Limits[4],Limits[5]) #displays the results#solves for the standard deviation of each set of data of interest
def custom_plot(volumes, energies, eos): plot.plot(volumes, energies, 'ro') x = np.linspace(min(eos.v), max(eos.v), 100) y = eval(eos.eos_string)(x, eos.eos_parameters[0], eos.eos_parameters[1], eos.eos_parameters[2], eos.eos_parameters[3]) plot.plot(x, y, label='fit') plot.xlabel('Volume ($\AA^3$)') plot.ylabel('Energy (eV)') plot.legend(loc='best') plot.savefig('eos.png') # show() if __name__ == '__main__': # load from file # volumes = np.loadtxt('filename')[:,0] # energies = np.loadtxt('filename')[:,1] # volumes = np.array([13.72, 14.83, 16.0, 17.23, 18.52]) # energies = np.array([-56.29, -56.41, -56.46, -56.46, -56.42]) volumes, energies = get_e_v('VOLUME') # eos = 'sjeos', 'murnaghan', 'birch', 'taylor', 'vinet' etc. eos = EquationOfState(volumes, energies, eos='murnaghan') v0, e0, B = eos.fit() # the ASE units for the bulk modulus is eV/Angstrom^3 print('optimum volume, energy and bulk moduls', v0, e0, B) # plot eos.plot(filename="eos_fit") # custom_plot(volumes, energies, eos)
def custom_plot(volumes, energies, eos): plot.plot(volumes, energies, 'ro') x = np.linspace(min(eos.v), max(eos.v), 100) y = eval(eos.eos_string)(x, eos.eos_parameters[0], eos.eos_parameters[1], eos.eos_parameters[2], eos.eos_parameters[3]) plot.plot(x, y, label='fit') plot.xlabel('Volume ($\AA^3$)') plot.ylabel('Energy (eV)') plot.legend(loc='best') plot.savefig('eos.png') #show() if __name__ == '__main__': #load from file #volumes = np.loadtxt('filename')[:,0] #energies = np.loadtxt('filename')[:,1] #volumes = np.array([13.72, 14.83, 16.0, 17.23, 18.52]) #energies = np.array([-56.29, -56.41, -56.46, -56.46, -56.42]) volumes, energies = get_e_v('VOLUME') #eos = 'sjeos', 'murnaghan', 'birch', 'taylor', 'vinet' etc. eos = EquationOfState(volumes, energies, eos='murnaghan') v0, e0, B = eos.fit() #the ASE units for the bulk modulus is eV/Angstrom^3 print('optimum volume, energy and bulk moduls', v0, e0, B) #plot eos.plot(filename="eos_fit") #custom_plot(volumes, energies, eos)
atoms.set_calculator(calc) nm_e = 0 nm_e = atoms.get_potential_energy() / atoms.get_number_of_atoms() nm_v = atoms.get_volume() / atoms.get_number_of_atoms() if nm_e < -0.001: volumes.append(nm_v) energies.append(nm_e) save(result, '{3} result : {0} {1} {2}'.format(opt, nm_v, nm_e, name)) print volumes, energies eos = EquationOfState(volumes, energies) v0, e0, B = eos.fit() eos.plot('{0}/graph/{1}.png'.format(temp_dir, name)) save(result, '{0} {1} {2} {3}'.format(v0, e0, B/kJ*1.0e24, (4.0 * v0) ** (1.0 / 3.0))) save(result, OPTIONS) save(result, volumes) save(result, energies) save(result, '------------------------') save(result_sum, '{0}, {1}, {2}, {3}, {4}, {5}'.format(name, e0, v0, B, volumes, energies))
def get_e_v(fname): data = np.loadtxt(fname, usecols=(1, 3, 5, 6, 7)) volumes = data[:, 1] energies = data[:, 4] return volumes, energies def custom_plot(volumes, energies, eos): plot.plot(volumes, energies, 'ro') x = np.linspace(min(eos.v), max(eos.v), 100) y = eval(eos.eos_string)(x, eos.eos_parameters[0], eos.eos_parameters[1], eos.eos_parameters[2], eos.eos_parameters[3]) plot.plot(x, y, label='fit') plot.xlabel('Volume ($\AA^3$)') plot.ylabel('Energy (eV)') plot.legend(loc='best') plot.savefig('eos.png') plot.show() if __name__ == '__main__': volumes, energies = get_e_v('test_bulk.txt') #eos = 'sjeos', 'murnaghan', 'birch', 'taylor', 'vinet' etc. eos = EquationOfState(volumes, energies, eos='murnaghan') v0, e0, B = eos.fit() #the ASE units for the bulk modulus is eV/Angstrom^3 print('optimum volume, energy and bulk moduls', v0, e0, B) #plot #eos.plot(filename= "eos_fit") custom_plot(volumes, energies, eos)
from vasp import Vasp from ase import Atom, Atoms from ase.utils.eos import EquationOfState import numpy as np LC = [3.75, 3.80, 3.85, 3.90, 3.95, 4.0, 4.05, 4.1] volumes, energies = [], [] for a in LC: atoms = Atoms( [Atom('Pd', (0, 0, 0))], cell=0.5 * a * np.array([[1.0, 1.0, 0.0], [0.0, 1.0, 1.0], [1.0, 0.0, 1.0]])) calc = Vasp('bulk/Pd-LDA-{0}'.format(a), encut=350, kpts=[12, 12, 12], xc='LDA', atoms=atoms) e = atoms.get_potential_energy() energies.append(e) volumes.append(atoms.get_volume()) calc.stop_if(None in energies) eos = EquationOfState(volumes, energies) v0, e0, B = eos.fit() print('LDA lattice constant is {0:1.3f} Ang^3'.format((4 * v0)**(1. / 3.)))
from ase.units import kJ from ase.utils.eos import EquationOfState lestim = lat0 volumes = [] energies = [] elstr=el1+el2+'-'+str for x in np.linspace(0.98, 1.02, 5): mys.set_cell(lestim * x, scale_atoms=True) volumes.append(mys.get_volume()/mys.get_number_of_atoms()) energies.append(mys.get_potential_energy()/mys.get_number_of_atoms()) print "Volumespa:", volumes print "Energiespa:", energies eos = EquationOfState(volumes, energies) vpa1, epa1, B1 = eos.fit() lpopt1 = pow(vpa1*(n1+n2)/vpc, 1/3.) print 'vpa1:', vpa1, 'A^3' print 'epa1:', epa1, 'eV' print 'B1:', B1 / kJ * 1.0e24, 'GPa' print 'lpopt1:', lpopt1 #eos.plot(elstr+'-eos.pdf')#,show=True) if binary == 1: hof = epa1+esub1*n1/(n1+n2)+esub2*n2/(n1+n2) else: hof = epa1/n1-esub1 print "hof1:", hof*1000, "meV/atom\n"
def get_eos(self, static=False): '''calculate the equation of state for the attached atoms. Returns a dictionary of data for each step. You do not need to specify any relaxation parameters, only the base parameters for the calculations. Writes to eos.org with a report of output. if static is True, then run a final static calculation at high precision, with ismear=-5. ''' # this returns if the data exists. if os.path.exists('eos.json'): with open('eos.json') as f: return json.loads(f.read()) # we need an initial calculation to get us going. self.calculate() cwd = os.getcwd() data = {'cwd': os.getcwd()} # dictionary to store results in org = [] # list of strings to make the org-file report org += ['#+STARTUP: showeverything'] org += ['* Initial guess'] org += [str(self)] org += ['', '[[shell:jaspsum -p {0}][view initial guess]]'.format(cwd)] with open('eos.org', 'w') as f: f.write('\n'.join(org)) atoms = self.get_atoms() original_atoms = atoms.copy() # save for comparison later. v_init = atoms.get_volume() # ############################################################ # ## Step 1 # ############################################################ org += ['* step 1 - relax ions and shape'] volumes1, energies1 = [], [] ready = True factors = [-0.15, -0.07, 0.0, 0.07, 0.15] for i, f in enumerate(factors): wd = cwd + '/step-1/f-{0}'.format(i) self.clone(wd) with jasp(wd, isif=4, ibrion=2, ediffg=-0.05, ediff=1e-6, nsw=50, atoms=atoms) as calc: try: # add org-link to calculation org += ['[[shell:jaspsum {0}][{0}]]'.format(wd)] atoms.set_volume(v_init * (1 + f)) volumes1.append(atoms.get_volume()) energies1.append(atoms.get_potential_energy()) calc.strip() except (VaspSubmitted, VaspQueued): ready = False if not ready: log.info('Step 1 is still running') raise VaspRunning data['step1'] = {} data['step1']['volumes'] = volumes1 data['step1']['energies'] = energies1 with open('eos.json', 'w') as f: f.write(json.dumps(data)) # create an org-table of the data. org += ['', '#+tblname: step1', '| volume (A^3) | Energy (eV) |', '|-'] for v, e in zip(volumes1, energies1): org += ['|{0}|{1}|'.format(v, e)] org += [''] with open('eos.org', 'w') as f: f.write('\n'.join(org)) eos1 = EquationOfState(volumes1, energies1) try: v1, e1, B1 = eos1.fit() except: with open('error', 'w') as f: f.write('Error fitting the equation of state') data['step1']['eos'] = (v1, e1, B1) with open('eos.json', 'w') as f: f.write(json.dumps(data)) # create a plot f = eos1.plot(show=False) f.subplots_adjust(left=0.18, right=0.9, top=0.9, bottom=0.15) plt.xlabel(u'volume ($\AA^3$)') plt.ylabel(u'energy (eV)') plt.title(u'E: %.3f eV, V: %.3f $\AA^3$, B: %.3f GPa' % (e1, v1, B1 / GPa)) plt.text(eos1.v0, max(eos1.e), 'EOS: %s' % eos1.eos_string) f.savefig('eos-step1.png') org += ['[[./eos-step1.png]]', ''] min_energy_index = np.argmin(energies1) if min_energy_index in [0, -1]: log.warn('Your minimum energy is at an endpoint.' 'This indicates something is wrong.') with open('eos.org', 'w') as f: f.write('\n'.join(org)) # ######################################################## # # STEP 2 # ######################################################## # step 2 - isif=4, ibrion=1. now we allow the shape of each cell to # change, and we use the best guess from step 1 for minimum volume. ready = True volumes2, energies2 = [], [] factors = [-0.09, -0.06, -0.03, 0.0, 0.03, 0.06, 0.09] org += ['* step 2 - relax ions and shape with improved minimum estimate'] for i, f in enumerate(factors): wd = cwd + '/step-2/f-{0}'.format(i) # clone closest result from above. with jasp('step-1/f-{0}'.format(min_energy_index)) as calc: calc.clone(wd) with jasp(wd, isif=4, ibrion=1, nsw=50) as calc: try: atoms = calc.get_atoms() atoms.set_volume(v1 * (1 + f)) volumes2 += [atoms.get_volume()] energies2 += [atoms.get_potential_energy()] calc.strip() except (VaspSubmitted, VaspQueued): ready = False if not ready: log.info('Step 2 is still running') raise VaspRunning # update org and json files. data['step2'] = {} data['step2']['volumes'] = volumes2 data['step2']['energies'] = energies2 with open('eos.json', 'w') as f: f.write(json.dumps(data)) # create an org-table of the data. org += ['', '#+tblname: step2', '| volume (A^3) | Energy (eV) |', '|-'] for v, e in zip(volumes2, energies2): org += ['|{0}|{1}|'.format(v, e)] org += [''] with open('eos.org', 'w') as f: f.write('\n'.join(org)) eos2 = EquationOfState(volumes2, energies2) try: v2, e2, B2 = eos2.fit() except: with open('error', 'w') as f: f.write('Error fitting the equation of state') data['step2']['eos'] = (v2, e2, B2) with open('eos.json', 'w') as f: f.write(json.dumps(data)) f = eos2.plot(show=False) f.subplots_adjust(left=0.18, right=0.9, top=0.9, bottom=0.15) plt.xlabel(u'volume ($\AA^3$)') plt.ylabel(u'energy (eV)') plt.title(u'E: %.3f eV, V: %.3f $\AA^3$, B: %.3f GPa' % (e2, v2, B2 / GPa)) plt.text(eos2.v0, max(eos2.e), 'EOS: %s' % eos2.eos_string) f.savefig('eos-step2.png') org += [ '[[./eos-step2.png]]', ''] with open('eos.org', 'w') as f: f.write('\n'.join(org)) # statistical analysis of the equation of state EOS = ['sjeos', 'taylor', 'murnaghan', 'birch', 'birchmurnaghan', 'pouriertarantola', 'vinet'] from ase.units import kJ Vs, Es, Bs = [], [], [] for label in EOS: eos = EquationOfState(volumes2, energies2, eos=label) try: v, e, B = eos.fit() Vs += [v] Es += [e] Bs += [B / kJ * 1.0e24] # GPa except: with open('error', 'w') as f: f.write('Error fitting the ' 'equation of state {0}'.format(label)) avgV = np.mean(Vs) stdV = np.std(Vs) avgE = np.mean(Es) stdE = np.std(Es) avgB = np.mean(Bs) stdB = np.std(Bs) from scipy.stats.distributions import t n = len(Vs) dof = n - 1 alpha = 0.05 Vconf = t.ppf(1 - alpha/2., dof) * stdV * np.sqrt(1 + 1./n) Bconf = t.ppf(1 - alpha/2., dof) * stdB * np.sqrt(1 + 1./n) data['step2']['avgV'] = avgV data['step2']['Vconf95'] = Vconf data['step2']['avgB'] = avgB data['step2']['Bconf95'] = Bconf org += ['** Statistical analysis', ''' Volume = {avgV:1.3f} \pm {Vconf:1.3f} \AA^3 at the 95% confidence level B = {avgB:1.0f} \pm {Bconf:1.0f} GPa at the 95% confidence level '''.format(**locals())] with open('eos.org', 'w') as f: f.write('\n'.join(org)) with open('eos.json', 'w') as f: f.write(json.dumps(data)) # step 3 should be isif = 3 where we let the volume change too # start from the minimum in step2 org += ['* step 3 - relax volume'] emin_ind = np.argmin(energies2) log.info('Minimum energy found in factor={0}.'.format(factors[emin_ind])) with jasp('step-2/f-{0}'.format(emin_ind)) as calc: calc.clone('step-3') with jasp('step-3', isif=3, # vol, shape and internal degrees of freedom ibrion=1, prec='high', nsw=50) as calc: atoms = calc.get_atoms() atoms.set_volume(avgV) calc.calculate() calc.strip() org += [str(calc)] atoms = calc.get_atoms() data['step3'] = {} data['step3']['potential_energy'] = atoms.get_potential_energy() data['step3']['volume'] = atoms.get_volume() with open('eos.org', 'w') as f: f.write('\n'.join(org)) with open('eos.json', 'w') as f: f.write(json.dumps(data)) # now the final step with ismear=-5 for the accurate energy. This # is recommended by the VASP manual. We only do this if you # specify static=True as an argument if static: with jasp('step-3') as calc: calc.clone('step-4') with jasp('step-4', isif=None, ibrion=None, nsw=None, icharg=2, # do not reuse charge istart=1, prec='high', ismear=-5) as calc: calc.calculate() atoms = calc.get_atoms() data['step4'] = {} data['step4']['potential_energy'] = atoms.get_potential_energy() org += ['* step-4 - static calculation', str(calc)] # final write out with open('eos.org', 'w') as f: f.write('\n'.join(org)) # dump data to a json file with open('eos.json', 'w') as f: f.write(json.dumps(data)) return data
from ase.io import read from ase.units import kJ from ase.utils.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')
from ase.lattice.cubic import FaceCenteredCubic from ase.calculators.emt import EMT from ase.utils.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. / 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))
encut=350, kpts=(6,6,6), isym=2, debug=logging.DEBUG, atoms=newatoms) calculators.append(calc) # now we set up the Pool of processes pool = multiprocessing.Pool(processes=3) # ask for 6 cores but run MPI on 2 cores # get the output from running each calculation out = pool.map(do_calculation, calculators) pool.close() pool.join() # this makes the script wait here until all jobs are done # now proceed with analysis V = [x[0] for x in out] E = [x[1] for x in out] eos = EquationOfState(V, E) v1, e1, B = eos.fit() print('step1: v1 = {v1}'.format(**locals())) ### ################################################################ ## STEP 2, eos around the minimum ## ################################################################# factors = [-0.06, -0.04, -0.02, 0.0, 0.02, 0.04, 0.06] calculators = [] # reset list for f in factors: newatoms = atoms.copy() newatoms.set_volume(v1*(1 + f)) label = 'bulk/cu-mp2/step2-{0}'.format(COUNTER) COUNTER += 1 calc = jasp(label,
xc='PBE', encut=350, kpts=(6,6,6), isym=2, atoms=newatoms) calculators.append(calc) # now we set up the Pool of processes pool = multiprocessing.Pool(processes=NCORES) # get the output from running each calculation out = pool.map(do_calculation, calculators) pool.close() pool.join() # this makes the script wait here until all jobs are done # now proceed with analysis V = [x[0] for x in out] E = [x[1] for x in out] eos = EquationOfState(V, E) v1, e1, B = eos.fit() print('step1: v1 = {v1}'.format(**locals())) ### ################################################################ ## STEP 2, eos around the minimum ## ################################################################# factors = [-0.06, -0.04, -0.02, 0.0, 0.02, 0.04, 0.06] calculators = [] # reset list for f in factors: newatoms = atoms.copy() newatoms.set_volume(v1*(1 + f)) label = 'bulk/cu-mp/step2-{0}'.format(COUNTER) COUNTER += 1 calc = jasp(label,
print("-----------------------------------------") print("Calculation output for Iron (fccFe) at 0K") print("-----------------------------------------") print(" Volumes Energies") for e, v in zip(v_Fe, e_Fe): print "{:<15} {:>10}".format(e, v) SAVE_PLOT = os.path.exists('./images') and os.path.isdir('./images') # Fit EOS print("----------------------------") print("Equation of state parameters") if not SAVE_PLOT: print("(to save a plot, mkdir 'images')") print("----------------------------") print(" E0 V0 B fit") files = [] for tag in ['vinet', 'birchmurnaghan']: eos = EquationOfState(v_Fe, e_Fe, eos=tag) v0, e0, B = eos.fit() print("{:2.6f} {:2.3f} {:2.1f} {:<16} ".format(e0, v0, B/GPa, tag)) if SAVE_PLOT: fname = 'images/fccFe-0K-eos-{0}.png'.format(tag) eos.plot(fname) files.append(fname) if SAVE_PLOT: print("Plots saved as {0}".format(", ".join([f for f in files])))