def test_direct_evaluation(self): a = FaceCenteredCubic('Au', size=[2,2,2]) a.rattle(0.1) calc = EAM('Au-Grochola-JCP05.eam.alloy') a.set_calculator(calc) f = a.get_forces() calc2 = EAM('Au-Grochola-JCP05.eam.alloy') i_n, j_n, dr_nc, abs_dr_n = neighbour_list('ijDd', a, cutoff=calc2.cutoff) epot, virial, f2 = calc2.energy_virial_and_forces(a.numbers, i_n, j_n, dr_nc, abs_dr_n) self.assertArrayAlmostEqual(f, f2) a = FaceCenteredCubic('Cu', size=[2,2,2]) calc = EAM('CuAg.eam.alloy') a.set_calculator(calc) FIRE(StrainFilter(a, mask=[1,1,1,0,0,0]), logfile=None).run(fmax=0.001) e_Cu = a.get_potential_energy()/len(a) a = FaceCenteredCubic('Ag', size=[2,2,2]) a.set_calculator(calc) FIRE(StrainFilter(a, mask=[1,1,1,0,0,0]), logfile=None).run(fmax=0.001) e_Ag = a.get_potential_energy()/len(a) self.assertTrue(abs(e_Ag+2.85)<1e-6) a = L1_2(['Ag', 'Cu'], size=[2,2,2], latticeconstant=4.0) a.set_calculator(calc) FIRE(UnitCellFilter(a, mask=[1,1,1,0,0,0]), logfile=None).run(fmax=0.001) e = a.get_potential_energy() syms = np.array(a.get_chemical_symbols()) self.assertTrue(abs((e-(syms=='Cu').sum()*e_Cu- (syms=='Ag').sum()*e_Ag)/len(a)-0.096)<0.0005) a = B1(['Ag', 'Cu'], size=[2,2,2], latticeconstant=4.0) a.set_calculator(calc) FIRE(UnitCellFilter(a, mask=[1,1,1,0,0,0]), logfile=None).run(fmax=0.001) e = a.get_potential_energy() syms = np.array(a.get_chemical_symbols()) self.assertTrue(abs((e-(syms=='Cu').sum()*e_Cu- (syms=='Ag').sum()*e_Ag)/len(a)-0.516)<0.0005) a = B2(['Ag', 'Cu'], size=[2,2,2], latticeconstant=4.0) a.set_calculator(calc) FIRE(UnitCellFilter(a, mask=[1,1,1,0,0,0]), logfile=None).run(fmax=0.001) e = a.get_potential_energy() syms = np.array(a.get_chemical_symbols()) self.assertTrue(abs((e-(syms=='Cu').sum()*e_Cu- (syms=='Ag').sum()*e_Ag)/len(a)-0.177)<0.0003) a = L1_2(['Cu', 'Ag'], size=[2,2,2], latticeconstant=4.0) a.set_calculator(calc) FIRE(UnitCellFilter(a, mask=[1,1,1,0,0,0]), logfile=None).run(fmax=0.001) e = a.get_potential_energy() syms = np.array(a.get_chemical_symbols()) self.assertTrue(abs((e-(syms=='Cu').sum()*e_Cu- (syms=='Ag').sum()*e_Ag)/len(a)-0.083)<0.0005)
def test_stress(self): a = FaceCenteredCubic('Au', size=[2,2,2]) calc = EAM('Au-Grochola-JCP05.eam.alloy') a.set_calculator(calc) self.assertArrayAlmostEqual(a.get_stress(), calc.calculate_numerical_stress(a), tol=self.tol) sx, sy, sz = a.cell.diagonal() a.set_cell([sx, 0.9*sy, 1.2*sz], scale_atoms=True) self.assertArrayAlmostEqual(a.get_stress(), calc.calculate_numerical_stress(a), tol=self.tol) a.set_cell([[sx, 0.1*sx, 0], [0, 0.9*sy, 0], [0, -0.1*sy, 1.2*sz]], scale_atoms=True) self.assertArrayAlmostEqual(a.get_stress(), calc.calculate_numerical_stress(a), tol=self.tol)
def test_rotation(self): for make_atoms, calc in [ # ( lambda a0,x : # FaceCenteredCubic('He', size=[1,1,1], # latticeconstant=3.5 if a0 is None else a0, # directions=x), # LJCut(epsilon=10.2, sigma=2.28, cutoff=5.0, shift=True) ), ( lambda a0,x : FaceCenteredCubic('Au', size=[1,1,1], latticeconstant=a0, directions=x), EAM('Au-Grochola-JCP05.eam.alloy') ), # ( lambda a0,x : Diamond('Si', size=[1,1,1], latticeconstant=a0, # directions=x), # Kumagai() ) #( lambda a0,x : FaceCenteredCubic('Au', size=[1,1,1], # latticeconstant=a0, directions=x), # EAM(potential='Au-Grochola-JCP05.eam.alloy') ), ]: a = make_atoms(None, [[1,0,0], [0,1,0], [0,0,1]]) a.set_calculator(calc) FIRE(StrainFilter(a, mask=[1,1,1,0,0,0]), logfile=None) \ .run(fmax=self.fmax) latticeconstant = np.mean(a.cell.diagonal()) C6 = measure_triclinic_elastic_constants(a, delta=self.delta, fmax=self.fmax) C11, C12, C44 = Voigt_6x6_to_cubic(C6)/GPa el = CubicElasticModuli(C11, C12, C44) C_m = measure_triclinic_elastic_constants(a, delta=self.delta, fmax=self.fmax)/GPa self.assertArrayAlmostEqual(el.stiffness(), C_m, tol=0.01) for directions in [ [[1,0,0], [0,1,0], [0,0,1]], [[0,1,0], [0,0,1], [1,0,0]], [[1,1,0], [0,0,1], [1,-1,0]], [[1,1,1], [-1,-1,2], [1,-1,0]] ]: a, b, c = directions directions = np.array([ np.array(x)/np.linalg.norm(x) for x in directions ]) a = make_atoms(latticeconstant, directions) a.set_calculator(calc) C = el.rotate(directions) C_check = el._rotate_explicit(directions) C_check2 = rotate_cubic_elastic_constants(C11, C12, C44, directions) C_check3 = \ rotate_elastic_constants(cubic_to_Voigt_6x6(C11, C12, C44), directions) self.assertArrayAlmostEqual(C, C_check, tol=1e-6) self.assertArrayAlmostEqual(C, C_check2, tol=1e-6) self.assertArrayAlmostEqual(C, C_check3, tol=1e-6) C_m = measure_triclinic_elastic_constants(a, delta=self.delta, fmax=self.fmax)/GPa self.assertArrayAlmostEqual(C, C_m, tol=1e-2)
def test_forces(self): for calc in [EAM('Au-Grochola-JCP05.eam.alloy')]: a = io.read('Au_923.xyz') a.center(vacuum=10.0) a.set_calculator(calc) f = a.get_forces() fn = calc.calculate_numerical_forces(a) self.assertArrayAlmostEqual(f, fn, tol=self.tol)
def test_hessian_amorphous_alloy(self): """Calculate Hessian matrix of amorphous alloy Reference: finite difference approximation of Hessian from ASE """ atoms = io.read('CuZr_glass_460_atoms.gz') atoms.pbc = [True, True, True] calculator = EAM('ZrCu.onecolumn.eam.alloy') self._test_hessian(atoms, calculator)
def test_CuAg(self): a = FaceCenteredCubic('Cu', size=[2, 2, 2]) calc = EAM('CuAg.eam.alloy') a.set_calculator(calc) FIRE(StrainFilter(a, mask=[1, 1, 1, 0, 0, 0]), logfile=None).run(fmax=0.001) e_Cu = a.get_potential_energy() / len(a) a = FaceCenteredCubic('Ag', size=[2, 2, 2]) a.set_calculator(calc) FIRE(StrainFilter(a, mask=[1, 1, 1, 0, 0, 0]), logfile=None).run(fmax=0.001) e_Ag = a.get_potential_energy() / len(a) self.assertTrue(abs(e_Ag + 2.85) < 1e-6) a = L1_2(['Ag', 'Cu'], size=[2, 2, 2], latticeconstant=4.0) a.set_calculator(calc) FIRE(UnitCellFilter(a, mask=[1, 1, 1, 0, 0, 0]), logfile=None).run(fmax=0.001) e = a.get_potential_energy() syms = np.array(a.get_chemical_symbols()) self.assertTrue( abs((e - (syms == 'Cu').sum() * e_Cu - (syms == 'Ag').sum() * e_Ag) / len(a) - 0.096) < 0.0005) a = B1(['Ag', 'Cu'], size=[2, 2, 2], latticeconstant=4.0) a.set_calculator(calc) FIRE(UnitCellFilter(a, mask=[1, 1, 1, 0, 0, 0]), logfile=None).run(fmax=0.001) e = a.get_potential_energy() syms = np.array(a.get_chemical_symbols()) self.assertTrue( abs((e - (syms == 'Cu').sum() * e_Cu - (syms == 'Ag').sum() * e_Ag) / len(a) - 0.516) < 0.0005) a = B2(['Ag', 'Cu'], size=[2, 2, 2], latticeconstant=4.0) a.set_calculator(calc) FIRE(UnitCellFilter(a, mask=[1, 1, 1, 0, 0, 0]), logfile=None).run(fmax=0.001) e = a.get_potential_energy() syms = np.array(a.get_chemical_symbols()) self.assertTrue( abs((e - (syms == 'Cu').sum() * e_Cu - (syms == 'Ag').sum() * e_Ag) / len(a) - 0.177) < 0.0003) a = L1_2(['Cu', 'Ag'], size=[2, 2, 2], latticeconstant=4.0) a.set_calculator(calc) FIRE(UnitCellFilter(a, mask=[1, 1, 1, 0, 0, 0]), logfile=None).run(fmax=0.001) e = a.get_potential_energy() syms = np.array(a.get_chemical_symbols()) self.assertTrue( abs((e - (syms == 'Cu').sum() * e_Cu - (syms == 'Ag').sum() * e_Ag) / len(a) - 0.083) < 0.0005)
def test_Grochola(self): a = FaceCenteredCubic('Au', size=[2,2,2]) calc = EAM('Au-Grochola-JCP05.eam.alloy') a.set_calculator(calc) FIRE(StrainFilter(a, mask=[1,1,1,0,0,0]), logfile=None).run(fmax=0.001) a0 = a.cell.diagonal().mean()/2 self.assertTrue(abs(a0-4.0701)<2e-5) self.assertTrue(abs(a.get_potential_energy()/len(a)+3.924)<0.0003) C, C_err = fit_elastic_constants(a, symmetry='cubic', verbose=False) C11, C12, C44 = Voigt_6x6_to_cubic(C) self.assertTrue(abs((C11-C12)/GPa-32.07)<0.7) self.assertTrue(abs(C44/GPa-45.94)<0.5)
def test_forces_CuZr_glass(self): """Calculate interatomic forces in CuZr glass Reference: tabulated forces from a calculation with Lammmps (git version patch_29Mar2019-2-g585403d65) The forces can be re-calculated using the following Lammps commands: units metal atom_style atomic boundary p p p read_data CuZr_glass_460_atoms.lammps.data.gz pair_style eam/alloy pair_coeff * * ZrCu.onecolumn.eam.alloy Zr Cu # The initial configuration is in equilibrium # and the remaining forces are small # Swap atom types to bring system out of # equilibrium and create nonzero forces group originally_Zr type 1 group originally_Cu type 2 set group originally_Zr type 2 set group originally_Cu type 1 run 0 write_dump all custom & CuZr_glass_460_atoms_forces.lammps.dump.gz & id type x y z fx fy fz & modify sort id format float "%.14g" """ format = "lammps-dump" if "lammps-dump" in io.formats.all_formats.keys( ) else "lammps-dump-text" atoms = io.read("CuZr_glass_460_atoms_forces.lammps.dump.gz", format=format) old_atomic_numbers = atoms.get_atomic_numbers() sel, = np.where(old_atomic_numbers == 1) new_atomic_numbers = np.zeros_like(old_atomic_numbers) new_atomic_numbers[sel] = 40 # Zr sel, = np.where(old_atomic_numbers == 2) new_atomic_numbers[sel] = 29 # Cu atoms.set_atomic_numbers(new_atomic_numbers) calculator = EAM('ZrCu.onecolumn.eam.alloy') atoms.set_calculator(calculator) atoms.pbc = [True, True, True] forces = atoms.get_forces() # Read tabulated forces and compare with gzip.open("CuZr_glass_460_atoms_forces.lammps.dump.gz") as file: for line in file: if line.startswith(b"ITEM: ATOMS "): # ignore header break dump = np.loadtxt(file) forces_dump = dump[:, 5:8] self.assertArrayAlmostEqual(forces, forces_dump, tol=self.force_tolerance)
def test_hessian_monoatomic_with_duplicate_pairs(self): """Calculate Hessian matrix of pure Cu In a small system, the same pair (i,j) will appear multiple times in the neighbor list, with different pair distance. Reference: finite difference approximation of Hessian from ASE """ atoms = FaceCenteredCubic('Cu', size=[2, 2, 2]) calculator = EAM('CuAg.eam.alloy') self._test_hessian(atoms, calculator)
def test_forces(self): for calc in [EAM('Au-Grochola-JCP05.eam.alloy')]: a = io.read('Au_923.xyz') a.center(vacuum=10.0) a.set_calculator(calc) f = a.get_forces() for i in range(9): atindex = i * 100 fn = [ numeric_force(a, atindex, 0, self.disp), numeric_force(a, atindex, 1, self.disp), numeric_force(a, atindex, 2, self.disp) ] self.assertArrayAlmostEqual(f[atindex], fn, tol=self.tol)
def test_dynamical_matrix(self): """Test dynamical matrix construction To obtain the dynamical matrix, one could either divide by masses immediately when constructing the matrix, or one could first form the complete Hessian and then divide by masses. The former method is implemented. """ atoms = io.read('CuZr_glass_460_atoms.gz') atoms.pbc = [True, True, True] calculator = EAM('ZrCu.onecolumn.eam.alloy') dynamical_matrix = calculator.calculate_hessian_matrix( atoms, divide_by_masses=True) # The second method requires a copy of Hessian, since # sparse matrix does not properly support *= operator hessian = calculator.calculate_hessian_matrix(atoms) masses = atoms.get_masses() mass_row = np.repeat(masses, np.diff(hessian.indptr)) mass_col = masses[hessian.indices] inverse_mass = np.sqrt(mass_row * mass_col)**-1.0 blocks = (inverse_mass * np.ones( (inverse_mass.size, 3, 3), dtype=inverse_mass.dtype).T).T nat = len(atoms) dynamical_matrix_ref = hessian.multiply( bsr_matrix((blocks, hessian.indices, hessian.indptr), shape=(3 * nat, 3 * nat))) dynamical_matrix = dynamical_matrix.todense() dynamical_matrix_ref = dynamical_matrix_ref.todense() self.assertArrayAlmostEqual(dynamical_matrix, dynamical_matrix.T, tol=self.hessian_tolerance) self.assertArrayAlmostEqual(dynamical_matrix_ref, dynamical_matrix_ref.T, tol=self.hessian_tolerance) self.assertArrayAlmostEqual(dynamical_matrix, dynamical_matrix_ref, tol=self.hessian_tolerance)
def test_elastic_constants_EAM(self): """Test the get_elastic_constants() function using matscipy EAM calculator.""" target_values = np.array([ 3.14339177996466, # alat 523.0266819809012, # C11 202.1786296941397, # C12 160.88179872237012 ]) # C44 for eam4 pot_name = "w_eam4.fs" calc_EAM = EAM(pot_name) obtained_values = sd.get_elastic_constants(calculator=calc_EAM, delta=1.0e-3) self.assertArrayAlmostEqual(obtained_values, target_values, tol=1e-4)
def test_funcfl(self): """Test eam kind 'eam' (DYNAMO funcfl format) variable da equal 0.02775 variable amin equal 2.29888527117067752084 variable amax equal 5.55*sqrt(2.0) variable i loop 201 label loop_head clear variable lattice_parameter equal ${amin}+${da}*${i} units metal atom_style atomic boundary p p p lattice fcc ${lattice_parameter} region box block 0 5 0 5 0 5 create_box 1 box pair_style eam pair_coeff * * Au_u3.eam create_atoms 1 box thermo 1 run 0 variable x equal pe variable potential_energy_fmt format x "%.14f" print "#a,E: ${lattice_parameter} ${potential_energy_fmt}" next i jump SELF loop_head # use # grep '^#a,E' log.lammps | awk '{print $2,$3}' > aE.txt # to extract info from log file The reference data was calculated using Lammps (git commit a73f1d4f037f670cd4295ecc1a576399a31680d2). """ da = 0.02775 amin = 2.29888527117067752084 amax = 5.55 * np.sqrt(2.0) for i in range(1, 202): latticeconstant = amin + i * da atoms = FaceCenteredCubic(symbol='Au', size=[5, 5, 5], pbc=(1, 1, 1), latticeconstant=latticeconstant) calc = EAM('Au-Grochola-JCP05.eam.alloy') atoms.set_calculator(calc) energy = atoms.get_potential_energy() print(energy)
def test_hessian_crystalline_alloy(self): """Calculate Hessian matrix of crystalline alloy Reference: finite difference approximation of Hessian from ASE """ calculator = EAM('ZrCu.onecolumn.eam.alloy') lattice_size = [4, 4, 4] # The lattice parameters are not correct, but that should be irrelevant # CuZr3 atoms = L1_2(['Cu', 'Zr'], size=lattice_size, latticeconstant=4.0) self._test_hessian(atoms, calculator) # Cu3Zr atoms = L1_2(['Zr', 'Cu'], size=lattice_size, latticeconstant=4.0) self._test_hessian(atoms, calculator) # CuZr atoms = B2(['Zr', 'Cu'], size=lattice_size, latticeconstant=3.3) self._test_hessian(atoms, calculator)
def test_CuZr(self): # This is a test for the potential published in: # Mendelev, Sordelet, Kramer, J. Appl. Phys. 102, 043501 (2007) a = FaceCenteredCubic('Cu', size=[2, 2, 2]) calc = EAM('CuZr_mm.eam.fs', kind='eam/fs') a.set_calculator(calc) FIRE(StrainFilter(a, mask=[1, 1, 1, 0, 0, 0]), logfile=None).run(fmax=0.001) a_Cu = a.cell.diagonal().mean() / 2 #print('a_Cu (3.639) = ', a_Cu) self.assertAlmostEqual(a_Cu, 3.639, 3) a = HexagonalClosedPacked('Zr', size=[2, 2, 2]) a.set_calculator(calc) FIRE(StrainFilter(a, mask=[1, 1, 1, 0, 0, 0]), logfile=None).run(fmax=0.001) a, b, c = a.cell / 2 #print('a_Zr (3.220) = ', norm(a), norm(b)) #print('c_Zr (5.215) = ', norm(c)) self.assertAlmostEqual(norm(a), 3.220, 3) self.assertAlmostEqual(norm(b), 3.220, 3) self.assertAlmostEqual(norm(c), 5.215, 3) # CuZr3 a = L1_2(['Cu', 'Zr'], size=[2, 2, 2], latticeconstant=4.0) a.set_calculator(calc) FIRE(UnitCellFilter(a, mask=[1, 1, 1, 0, 0, 0]), logfile=None).run(fmax=0.001) self.assertAlmostEqual(a.cell.diagonal().mean() / 2, 4.324, 3) # Cu3Zr a = L1_2(['Zr', 'Cu'], size=[2, 2, 2], latticeconstant=4.0) a.set_calculator(calc) FIRE(UnitCellFilter(a, mask=[1, 1, 1, 0, 0, 0]), logfile=None).run(fmax=0.001) self.assertAlmostEqual(a.cell.diagonal().mean() / 2, 3.936, 3) # CuZr a = B2(['Zr', 'Cu'], size=[2, 2, 2], latticeconstant=3.3) a.set_calculator(calc) FIRE(UnitCellFilter(a, mask=[1, 1, 1, 0, 0, 0]), logfile=None).run(fmax=0.001) self.assertAlmostEqual(a.cell.diagonal().mean() / 2, 3.237, 3)
def _test_for_size(size): atoms = FaceCenteredCubic('Cu', size=size) calculator = EAM('CuAg.eam.alloy') self._test_hessian(atoms, calculator)
def test_mix_eam_alloy(self): if False: source, parameters, F, f, rep = read_eam("CuAu_Zhou.eam.alloy", kind="eam/alloy") source1, parameters1, F1, f1, rep1 = mix_eam( ["Cu_Zhou.eam.alloy", "Au_Zhou.eam.alloy"], "eam/alloy", "weight") write_eam(source1, parameters1, F1, f1, rep1, "CuAu_mixed.eam.alloy", kind="eam/alloy") calc0 = EAM('CuAu_Zhou.eam.alloy') calc1 = EAM('CuAu_mixed.eam.alloy') a = FaceCenteredCubic('Cu', size=[2, 2, 2]) a.set_calculator(calc0) FIRE(StrainFilter(a, mask=[1, 1, 1, 0, 0, 0]), logfile=None).run(fmax=0.001) e0 = a.get_potential_energy() / len(a) a = FaceCenteredCubic('Cu', size=[2, 2, 2]) a.set_calculator(calc1) FIRE(StrainFilter(a, mask=[1, 1, 1, 0, 0, 0]), logfile=None).run(fmax=0.001) e1 = a.get_potential_energy() / len(a) self.assertTrue(e0 - e1 < 0.0005) a = FaceCenteredCubic('Au', size=[2, 2, 2]) a.set_calculator(calc0) FIRE(StrainFilter(a, mask=[1, 1, 1, 0, 0, 0]), logfile=None).run(fmax=0.001) e0 = a.get_potential_energy() / len(a) a = FaceCenteredCubic('Au', size=[2, 2, 2]) a.set_calculator(calc1) FIRE(StrainFilter(a, mask=[1, 1, 1, 0, 0, 0]), logfile=None).run(fmax=0.001) e1 = a.get_potential_energy() / len(a) self.assertTrue(e0 - e1 < 0.0005) a = L1_2(['Au', 'Cu'], size=[2, 2, 2], latticeconstant=4.0) a.set_calculator(calc0) FIRE(UnitCellFilter(a, mask=[1, 1, 1, 0, 0, 0]), logfile=None).run(fmax=0.001) e0 = a.get_potential_energy() / len(a) a = L1_2(['Au', 'Cu'], size=[2, 2, 2], latticeconstant=4.0) a.set_calculator(calc1) FIRE(UnitCellFilter(a, mask=[1, 1, 1, 0, 0, 0]), logfile=None).run(fmax=0.001) e1 = a.get_potential_energy() / len(a) self.assertTrue(e0 - e1 < 0.0005) a = L1_2(['Cu', 'Au'], size=[2, 2, 2], latticeconstant=4.0) a.set_calculator(calc0) FIRE(UnitCellFilter(a, mask=[1, 1, 1, 0, 0, 0]), logfile=None).run(fmax=0.001) e0 = a.get_potential_energy() / len(a) a = L1_2(['Cu', 'Au'], size=[2, 2, 2], latticeconstant=4.0) a.set_calculator(calc1) FIRE(UnitCellFilter(a, mask=[1, 1, 1, 0, 0, 0]), logfile=None).run(fmax=0.001) e1 = a.get_potential_energy() / len(a) self.assertTrue(e0 - e1 < 0.0005) a = B1(['Au', 'Cu'], size=[2, 2, 2], latticeconstant=4.0) a.set_calculator(calc0) FIRE(UnitCellFilter(a, mask=[1, 1, 1, 0, 0, 0]), logfile=None).run(fmax=0.001) e0 = a.get_potential_energy() / len(a) a = B1(['Au', 'Cu'], size=[2, 2, 2], latticeconstant=4.0) a.set_calculator(calc1) FIRE(UnitCellFilter(a, mask=[1, 1, 1, 0, 0, 0]), logfile=None).run(fmax=0.001) e1 = a.get_potential_energy() / len(a) self.assertTrue(e0 - e1 < 0.0005) os.remove("CuAu_mixed.eam.alloy")