def aucu_phonons(): N = 7 atoms = bulk("Au", crystalstructure="fcc", a=4.08) calc = EMT() atoms.set_calculator(calc) ph = Phonons(atoms, calc, supercell=(N, N, N), delta=0.05) ph.run() ph.read(acoustic=True) ph.clean() omega_e_au, dos_e_au = ph.dos(kpts=(50, 50, 50), npts=1000, delta=5E-4) atoms = bulk("Cu", crystalstructure="fcc", a=3.62) atoms.set_calculator(calc) ph = Phonons(atoms, calc, supercell=(N, N, N), delta=0.05) ph.run() ph.read(acoustic=True) ph.clean() omega_e_cu, dos_e_cu = ph.dos(kpts=(13, 13, 13), npts=100, delta=5E-4) fig = plt.figure() ax = fig.add_subplot(1, 1, 1) ax.plot(omega_e_au * 1000.0, dos_e_au) ax.plot(omega_e_cu * 1000.0, dos_e_cu) ax.set_xlabel("Energy (meV)") logw_au = np.sum(np.log(omega_e_au[1:]) * dos_e_au[1:]) logw_cu = np.sum(np.log(omega_e_cu[1:]) * dos_e_cu[1:]) print(logw_au, logw_cu, logw_au - logw_cu) plt.show()
def getLJeigenvaluesB(X, S, epsilon, sigma, rc, getForceMatrix): from ase import Atoms from ase.build import bulk from ase.calculators.lj import LennardJones from ase.phonons import Phonons import numpy as np from scipy import linalg as LA calc = LennardJones(sigma=sigma, epsilon=epsilon, rc=rc) # chemStr = 'H' + str(len(X)) # atoms = Atoms(chemStr, X, calculator=calc ) atoms = Atoms(getChemStr(S), X, calculator=calc) energy = atoms.get_potential_energy() eig = [] if getForceMatrix: ph = Phonons(atoms, calc) ph.run() ph.read(acoustic=True) ph.clean() f = ph.get_force_constant() (l, m, n) = f.shape if l == 1: ff = np.reshape(f, (m, n)) else: print("error") # eig = LA.eigvalsh(ff) # eig is a numpy array # return energy, [float("{0:.5f}".format(eig[i])) for i in range(len(eig))]
def _calculate_finite_difference_hessian(self, atoms, calculator): """Calcualte the Hessian matrix using finite differences.""" ph = Phonons(atoms, calculator, supercell=(1, 1, 1), delta=1e-6) ph.clean() ph.run() ph.read(acoustic=False) ph.clean() H_numerical = ph.get_force_constant()[0, :, :] return H_numerical
def test_hessian(self): for calc in [{(1, 1): LennardJonesQuadratic(1, 1, 3), (1, 2): LennardJonesQuadratic(1.5, 0.8, 2.4), (2, 2): LennardJonesQuadratic(0.5, 0.88, 2.64)}]: atoms = io.read("KA256_Min.xyz") atoms.center(vacuum=5.0) b = calculator.PairPotential(calc) H_analytical = b.calculate_hessian_matrix(atoms, "dense") # Numerical ph = Phonons(atoms, b, supercell=(1, 1, 1), delta=0.001) ph.run() ph.read(acoustic=False) ph.clean() H_numerical = ph.get_force_constant()[0, :, :] self.assertArrayAlmostEqual(H_analytical, H_numerical, tol=0.03)
def get_dos( model, posinp, device="cpu", supercell=(6, 6, 6), qpoints=[30, 30, 30], npts=1000, width=0.004, ): if isinstance(posinp, str): atoms = posinp_to_ase_atoms(Posinp.from_file(posinp)) elif isinstance(posinp, Posinp): atoms = posinp_to_ase_atoms(posinp) else: raise ValueError("The posinp variable is not recognized.") if isinstance(model, str): model = load_model(model, map_location=device) elif isinstance(model, torch.nn.Module): pass else: raise ValueError("The model variable is not recognized.") # Bugfix to make older models work with PyTorch 1.6 # Hopefully temporary for mod in model.modules(): if not hasattr(mod, "_non_persistent_buffers_set"): mod._non_persistent_buffers_set = set() assert len(supercell) == 3, "Supercell should be a length 3 object." assert len(qpoints) == 3, "Qpoints should be a length 3 object." supercell = tuple(supercell) cutoff = float(model.state_dict() ["representation.interactions.0.cutoff_network.cutoff"]) calculator = SpkCalculator( model, device=device, energy="energy", forces="forces", environment_provider=AseEnvironmentProvider(cutoff), ) ph = Phonons(atoms, calculator, supercell=supercell, delta=0.02) ph.run() ph.read(acoustic=True) dos = ph.get_dos(kpts=qpoints).sample_grid(npts=npts, width=width) ph.clean() return Dos(dos.energy * 8065.6, dos.weights[0])
def test_hessian(self): for calc in [{ (1, 1): LennardJonesQuadratic(1, 1, 3), (1, 2): LennardJonesQuadratic(1.5, 0.8, 2.4), (2, 2): LennardJonesQuadratic(0.5, 0.88, 2.64) }]: atoms = io.read("KA256_Min.xyz") atoms.center(vacuum=5.0) b = calculator.PairPotential(calc) H_analytical = b.calculate_hessian_matrix(atoms, "dense") # Numerical ph = Phonons(atoms, b, supercell=(1, 1, 1), delta=0.001) ph.run() ph.read(acoustic=False) ph.clean() H_numerical = ph.get_force_constant()[0, :, :] self.assertArrayAlmostEqual(H_analytical, H_numerical, tol=0.03)
def calculate_phonons(x): # Setup crystal and EMT calculator atoms = bulk('Al', 'fcc', a=x) #4.05) # Phonon calculator N = 7 ph = Phonons(atoms, EMT(), supercell=(N, N, N), delta=0.05) ph.run() # Read forces and assemble the dynamical matrix ph.read(acoustic=True) ph.clean() path = atoms.cell.bandpath('GXULGK', npoints=100) bs = ph.get_band_structure(path) dos = ph.get_dos(kpts=(20, 20, 20)).sample_grid(npts=100, width=1e-3) forces = ph.get_force_constant() print(forces) # Plot the band structure and DOS: import matplotlib.pyplot as plt fig = plt.figure(1, figsize=(8, 4), dpi=300) ax = fig.add_axes([.12, .07, .67, .85]) emax = 0.035 bs.plot(ax=ax, emin=-0.01, emax=emax) dosax = fig.add_axes([.8, .07, .17, .85]) dosax.fill_between(dos.weights[0], dos.energy, y2=0, color='grey', edgecolor='k', lw=1) dosax.set_ylim(-0.01, emax) dosax.set_yticks([]) dosax.set_xticks([]) dosax.set_xlabel("DOS", fontsize=18) fig.savefig('Al_phonon.png') return
def getLJeigenvalues(listOfPositions, epsilon, sigma, rc, getForceMatrix): from ase import Atoms from ase.build import bulk from ase.calculators.lj import LennardJones from ase.phonons import Phonons import numpy as np from scipy import linalg as LA # from gpaw import GPAW, FermiDirac # calc = LennardJones() #a.set_calculator(calc) # atoms = bulk('Si', 'diamond', a=5.4) # atoms = bulk('H', 'fcc', a=1.1, cubic=True) #atoms = Atoms('N3', [(0, 0, 0), (0, 0, 1.1), (0, 0, 2.2)], calculator=LennardJones() ) # atoms = Atoms('H2', [(0, 0, 0), (0, 0, 1.12246)], calculator=LennardJones() ) # calc = GPAW(kpts=(5, 5, 5), h=0.2, occupations=FermiDirac(0.)) chemStr = 'H' + str(len(listOfPositions)) calc = LennardJones(sigma=sigma, epsilon=epsilon, rc=rc) atoms = Atoms(chemStr, listOfPositions, calculator=calc) energy = atoms.get_potential_energy() eig = [] if getForceMatrix: ph = Phonons(atoms, calc) ph.run() ph.read(acoustic=True) ph.clean() f = ph.get_force_constant() # f # f.size (l, m, n) = f.shape if l == 1: ff = np.reshape(f, (m, n)) else: print("error") # # ff eig = LA.eigvalsh(ff) # eig is a numpy array # return energy, [float("{0:.5f}".format(eig[i])) for i in range(len(eig))]
def getEnergyAndEigen(self, aseStruct): aseStruct.set_calculator(self.calc) energy = aseStruct.get_potential_energy() eig = [] ph = Phonons(aseStruct, self.calc) ph.run() ph.read(acoustic=True) ph.clean() f = ph.get_force_constant() (l, m, n) = f.shape if l == 1: ff = np.reshape(f, (m, n)) else: print("error") # eig = LA.eigvalsh(ff) # eig is a numpy array # return energy, [ float("{0:.5f}".format(eig[i])) for i in range(len(eig)) ]
def getLJeigenvalues2B(X, S, epsilon, sigma, rc, getForceMatrix, aCell): from ase import Atoms from ase.build import bulk from ase.phonons import Phonons import numpy as np from scipy import linalg as LA from ase import Atom, Atoms from lammpslib import LAMMPSlib # chemStr = 'H' + str(len(X)) # struct = Atoms(chemStr, X, cell=(aCell, aCell, aCell), pbc=True) struct = Atoms(getChemStr(S), X, cell=(aCell, aCell, aCell), pbc=True) lammps_header = ["units metal"] cmds = [ "pair_style mlip /Users/chinchay/Documents/9_Git/reverseEnergyPartitioning/mlip_LJ.ini",\ "pair_coeff * * " ] mylammps = LAMMPSlib( lmpcmds=cmds, atom_types={1: 1}, keep_alive=True, log_file= '/Users/chinchay/Documents/9_Git/reverseEnergyPartitioning/log.txt') struct.set_calculator(mylammps) energy = struct.get_potential_energy() eig = [] if getForceMatrix: ph = Phonons(struct, mylammps) ph.run() ph.read(acoustic=True) ph.clean() f = ph.get_force_constant() (l, m, n) = f.shape if l == 1: ff = np.reshape(f, (m, n)) else: print("error") # eig = LA.eigvalsh(ff) # eig is a numpy array # return energy, [float("{0:.5f}".format(eig[i])) for i in range(len(eig))]
def test_phonon_md_init(asap3): # Tests the phonon-based perturbation and velocity distribution # for thermal equilibration in MD. EMT = asap3.EMT rng = RandomState(17) atoms = bulk('Pd') atoms *= (3, 3, 3) avail = [atomic_numbers[sym] for sym in ['Ni', 'Cu', 'Pd', 'Ag', 'Pt', 'Au']] atoms.numbers[:] = rng.choice(avail, size=len(atoms)) atoms.calc = EMT() opt = FIRE(atoms, trajectory='relax.traj') opt.run(fmax=0.001) positions0 = atoms.positions.copy() phonons = Phonons(atoms, EMT(), supercell=(1, 1, 1), delta=0.05) try: phonons.run() phonons.read() # Why all this boilerplate? finally: phonons.clean() matrices = phonons.get_force_constant() K = matrices[0] T = 300 * units.kB atoms.calc = EMT() Epotref = atoms.get_potential_energy() temps = [] Epots = [] Ekins = [] Etots = [] for i in range(24): PhononHarmonics(atoms, K, T, quantum=True, rng=np.random.RandomState(888 + i)) Epot = atoms.get_potential_energy() - Epotref Ekin = atoms.get_kinetic_energy() Ekins.append(Ekin) Epots.append(Epot) Etots.append(Ekin + Epot) temps.append(atoms.get_temperature()) atoms.positions[:] = positions0 # The commented code would produce displacements/velocities # resolved over phonon modes if we borrow some expressions # from the function. Each mode should contribute on average # equally to both Epot and Ekin/temperature # # atoms1.calc = EMT() # atoms1 = atoms.copy() # v_ac = np.zeros_like(positions0) # D_acs, V_acs = ... # for s in range(V_acs.shape[2]): # atoms1.positions += D_acs[:, :, s] # v_ac += V_acs[:, :, s] # atoms1.set_velocities(v_ac) # X1.append(atoms1.get_potential_energy() - Epotref) # X2.append(atoms1.get_kinetic_energy()) print('energies', Epot, Ekin, Epot + Ekin) Epotmean = np.mean(Epots) Ekinmean = np.mean(Ekins) Tmean = np.mean(temps) Terr = abs(Tmean - T / units.kB) relative_imbalance = abs(Epotmean - Ekinmean) / (Epotmean + Ekinmean) print('epotmean', Epotmean) print('ekinmean', Ekinmean) print('rel imbalance', relative_imbalance) print('Tmean', Tmean, 'Tref', T / units.kB, 'err', Terr) assert Terr < 0.1*T / units.kB, Terr # error in Kelvin for instantaneous velocity # Epot == Ekin give or take 2 %: assert relative_imbalance < 0.1, relative_imbalance if 0: import matplotlib.pyplot as plt I = np.arange(len(Epots)) plt.plot(I, Epots, 'o', label='pot') plt.plot(I, Ekins, 'o', label='kin') plt.plot(I, Etots, 'o', label='tot') plt.show()
def ase_phonon_calc( struct, calc=None, kpoints=[1, 1, 1], ftol=0.01, force_clean=False, name="asephonon", ): """Calculate phonon modes of a molecule using ASE and a given calculator. The system will be geometry optimized before calculating the modes. A report of the phonon modes will be written to a file and arrays of the eigenvectors and eigenvalues returned. | Args: | struct (ase.Atoms): Atoms object with to calculate modes for. | calc (ase.Calculator): Calculator for energies and forces (if not | present, use the one from struct) | kpoints (np.ndarray): Kpoint grid for phonon calculation. If None, just | do a Vibration modes calculation (default is [1,1,1]) | ftol (float): Tolerance for geometry optimisation (default | is 0.01 eV/Ang) | force_clean (bool): If True, force a deletion of all phonon files | and recalculate them | Returns: | evals (float[k-points][modes]): Eigenvalues of phonon modes | evecs (float[k-points][modes][ions][3]): Eigenvectors of phonon modes | struct (ase.Atoms): Optimised structure """ N = len(struct) if calc is None: calc = struct.calc struct = struct.copy() calc.atoms = struct struct.calc = calc dyn = BFGS(struct, trajectory="geom_opt.traj") dyn.run(fmax=ftol) # Calculate phonon modes vib_pbc = kpoints is not None if vib_pbc: vib = Phonons(struct, calc, name=name) else: vib = Vibrations(struct, name=name) if force_clean: vib.clean() vib.run() if vib_pbc: vib.read(acoustic=True) path = monkhorst_pack(kpoints) evals, evecs = vib.band_structure(path, True) else: vib.read() path = np.zeros((1, 3)) # One axis added since it's like the gamma point evals = np.real(vib.get_energies()[None]) evecs = np.array([vib.get_mode(i) for i in range(3 * N)])[None] # eV to cm^-1 evals *= ((cnst.electron_volt / cnst.h) / cnst.c) / 100.0 # Normalise eigenvectors evecs /= np.linalg.norm(evecs, axis=(2, 3))[:, :, None, None] return ASEPhononData(evals, evecs, path, struct)
# creates: Al_phonon.png from ase.build import bulk from ase.calculators.emt import EMT from ase.phonons import Phonons # Setup crystal and EMT calculator atoms = bulk('Al', 'fcc', a=4.05) # Phonon calculator N = 7 ph = Phonons(atoms, EMT(), supercell=(N, N, N), delta=0.05) ph.run() # Read forces and assemble the dynamical matrix ph.read(acoustic=True) ph.clean() path = atoms.cell.bandpath('GXULGK', npoints=100) bs = ph.get_band_structure(path) dos = ph.get_dos(kpts=(20, 20, 20)).sample_grid(npts=100, width=1e-3) # Plot the band structure and DOS: import matplotlib.pyplot as plt fig = plt.figure(1, figsize=(7, 4)) ax = fig.add_axes([.12, .07, .67, .85]) emax = 0.035 bs.plot(ax=ax, emin=0.0, emax=emax) dosax = fig.add_axes([.8, .07, .17, .85])
def getLJeigenvalues2(listOfPositions, epsilon, sigma, rc, getForceMatrix, aCell): from ase import Atoms from ase.build import bulk # from ase.calculators.lj import LennardJones from ase.phonons import Phonons import numpy as np from scipy import linalg as LA # from gpaw import GPAW, FermiDirac # calc = LennardJones() #a.set_calculator(calc) # atoms = bulk('Si', 'diamond', a=5.4) # atoms = bulk('H', 'fcc', a=1.1, cubic=True) #atoms = Atoms('N3', [(0, 0, 0), (0, 0, 1.1), (0, 0, 2.2)], calculator=LennardJones() ) # atoms = Atoms('H2', [(0, 0, 0), (0, 0, 1.12246)], calculator=LennardJones() ) # calc = GPAW(kpts=(5, 5, 5), h=0.2, occupations=FermiDirac(0.)) # d = 1.122 # = 2**(1/6) # a = 10.00 # struct = Atoms( 'H2', positions=[(0, 0, 0), (0, 0, d)] , cell=(a, a, a), pbc=True ) chemStr = 'H' + str(len(listOfPositions)) # struct = Atoms(chemStr, listOfPositions, cell=(aCell, aCell, aCell)) # <<< without pbc=True you would need a very large aCell value! struct = Atoms(chemStr, listOfPositions, cell=(aCell, aCell, aCell), pbc=True) # struct = Atoms(chemStr, positions=positions , cell=(aCell, aCell, aCell), pbc=True ) ############################################################################ # from ase.calculators.lj import LennardJones # calc = LennardJones(sigma=sigma, epsilon=epsilon, rc=rc) # struct = Atoms(chemStr, listOfPositions, calculator=calc ) ############################################################################ from ase import Atom, Atoms from lammpslib import LAMMPSlib # lammps_header=['units metal' ,\ # 'boundary p p p ' ,\ # "atom_style atomic" ,\ # "atom_modify map hash" ] lammps_header = ["units metal"] cmds = [ "pair_style mlip /Users/chinchay/Documents/9_Git/reverseEnergyPartitioning/mlip_LJ.ini",\ "pair_coeff * * " ] # cmds = ["pair_style mlip /Users/chinchay/Documents/9_Git/reverseEnergyPartitioning/mlip_LJ.ini",\ # "pair_coeff * * " ,\ # "neighbor 1.5 bin " ] # cmds = ["pair_style mlip /Users/chinchay/Documents/9_Git/reverseEnergyPartitioning/mlip_test.ini",\ # "pair_coeff * * " ,\ # "neighbor 1.5 bin " ] mylammps = LAMMPSlib( lmpcmds=cmds, atom_types={1: 1}, keep_alive=True, log_file= '/Users/chinchay/Documents/9_Git/reverseEnergyPartitioning/log.txt') # struct = Atoms(chemStr, listOfPositions, calculator=mylammps ) struct.set_calculator(mylammps) ############################################################################ energy = struct.get_potential_energy() eig = [] if getForceMatrix: # ph = Phonons(struct, calc) ph = Phonons(struct, mylammps) ph.run() ph.read(acoustic=True) ph.clean() f = ph.get_force_constant() # f # f.size (l, m, n) = f.shape if l == 1: ff = np.reshape(f, (m, n)) else: print("error") # # ff eig = LA.eigvalsh(ff) # eig is a numpy array # return energy, [float("{0:.5f}".format(eig[i])) for i in range(len(eig))]
atoms *= (3, 3, 3) avail = [atomic_numbers[sym] for sym in ['Ni', 'Cu', 'Pd', 'Ag', 'Pt', 'Au']] atoms.numbers[:] = rng.choice(avail, size=len(atoms)) atoms.calc = EMT() opt = FIRE(atoms, trajectory='relax.traj') opt.run(fmax=0.001) positions0 = atoms.positions.copy() phonons = Phonons(atoms, EMT(), supercell=(1, 1, 1), delta=0.05) try: phonons.run() phonons.read() # Why all this boilerplate? finally: phonons.clean() matrices = phonons.get_force_constant() K = matrices[0] T = 300 * units.kB atoms.calc = EMT() Epotref = atoms.get_potential_energy() temps = [] Epots = [] Ekins = [] Etots = [] for i in range(24): PhononHarmonics(atoms,