def testForceAgainstDefaultNeighborList(self): atoms = Diamond(symbol="C", pbc=False) builtin = torchani.neurochem.Builtins() calculator = torchani.ase.Calculator(builtin.species, builtin.aev_computer, builtin.models, builtin.energy_shifter) default_neighborlist_calculator = torchani.ase.Calculator( builtin.species, builtin.aev_computer, builtin.models, builtin.energy_shifter, True) atoms.set_calculator(calculator) dyn = Langevin(atoms, 5 * units.fs, 50 * units.kB, 0.002) def test_energy(a=atoms): a = a.copy() a.set_calculator(calculator) e1 = a.get_potential_energy() a.set_calculator(default_neighborlist_calculator) e2 = a.get_potential_energy() self.assertLess(abs(e1 - e2), tol) dyn.attach(test_energy, interval=1) dyn.run(500)
def testEqualOneModelPTI(self): calculator_pti = self.model_pti[0].ase() calculator = self.model[0].ase() atoms = Diamond(symbol="C", pbc=True) atoms_pti = Diamond(symbol="C", pbc=True) atoms.set_calculator(calculator) atoms_pti.set_calculator(calculator_pti) self.assertEqual(atoms.get_potential_energy(), atoms_pti.get_potential_energy())
def testWithNumericalForceWithPBCEnabled(self): atoms = Diamond(symbol="C", pbc=True) calculator = torchani.models.ANI1x().ase() atoms.set_calculator(calculator) dyn = Langevin(atoms, 5 * units.fs, 30000000 * units.kB, 0.002) dyn.run(100) f = torch.from_numpy(atoms.get_forces()) fn = get_numeric_force(atoms, 0.001) df = (f - fn).abs().max() avgf = f.abs().mean() if avgf > 0: self.assertLess(df / avgf, 0.1)
def testWithNumericalForceWithPBCEnabled(self): # Run a Langevin thermostat dynamic for 100 steps and after the dynamic # check once that the numerical and analytical force agree to a given # relative tolerance atoms = Diamond(symbol="C", pbc=True) calculator = self.model.ase() atoms.set_calculator(calculator) dyn = Langevin(atoms, 5 * units.fs, 30000000 * units.kB, 0.002) dyn.run(100) f = atoms.get_forces() fn = get_numeric_force(atoms, 0.001) self.assertEqual(f, fn, rtol=0.1, atol=0.1)
def _testForce(self, pbc): atoms = Diamond(symbol="C", pbc=pbc) builtin = torchani.neurochem.Builtins() calculator = torchani.ase.Calculator( builtin.species, builtin.aev_computer, builtin.models, builtin.energy_shifter) atoms.set_calculator(calculator) dyn = Langevin(atoms, 5 * units.fs, 30000000 * units.kB, 0.002) dyn.run(100) f = torch.from_numpy(atoms.get_forces()) fn = get_numeric_force(atoms, 0.001) df = (f - fn).abs().max() avgf = f.abs().mean() if avgf > 0: self.assertLess(df / avgf, 0.1)
def test_pbc(self): a = Diamond('Si', latticeconstant=5.432, size=[2,2,2]) sx, sy, sz = a.get_cell().diagonal() a.set_calculator(Tersoff()) e1 = a.get_potential_energy() a.set_pbc([True,True,False]) e2 = a.get_potential_energy() a.set_pbc(True) a.set_cell([sx,sy,2*sz]) e3 = a.get_potential_energy() self.assertEqual(e2, e3) # This should give the unrelaxed surface energy esurf = (e2-e1)/(2*sx*sy) * Jm2 self.assertTrue(abs(esurf-2.309) < 0.001)
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 MD(): old_stdout = sys.stdout sys.stdout = mystdout = StringIO() orig_stdout = sys.stdout f = open('out.txt', 'w') sys.stdout = f #f = open('out_' + str(temp) + '.txt', 'w') #sys.stdout = f Tmin = 1000 Tmax = 15000 a0 = 5.43 N = 1 atoms = Diamond(symbol='Si', latticeconstant=a0) atoms *= (N, N, N) atoms.set_calculator(model.calculator) MaxwellBoltzmannDistribution(atoms, Tmin * units.kB) ###is this allowed? Stationary(atoms) # zero linear momentum ZeroRotation(atoms) def printenergy(a=atoms): epot = a.get_potential_energy() / len(a) ekin = a.get_kinetic_energy() / len(a) print(ekin) traj = Trajectory('Si.traj', 'w', atoms) for temp in np.linspace(Tmin, Tmax, 5): dyn = Langevin(atoms, 5 * units.fs, units.kB * temp, 0.002) dyn.attach(traj.write, interval=1) dyn.attach(printenergy, interval=1) dyn.run(100) sys.stdout = orig_stdout f.close()
print_crack_system(directions) # now, we build system aligned with requested crystallographic orientation unit_slab = Diamond(directions=directions, size=(1, 1, 1), symbol='Si', pbc=True, latticeconstant=a0) if (hasattr(params, 'check_rotated_elastic_constants') and # Check that elastic constants of the rotated system # lead to same Young's modulus and Poisson ratio params.check_rotated_elastic_constants): unit_slab.set_calculator(params.calc) C_r1 = measure_triclinic_elastic_constants(unit_slab, optimizer=FIRE, fmax=params.bulk_fmax) R = np.array([ np.array(x)/np.linalg.norm(x) for x in directions ]) C_r2 = rotate_elastic_constants(C, R) for C_r in [C_r1, C_r2]: S_r = np.linalg.inv(C_r) E_r = 1./S_r[1,1] print('Young\'s modulus from C_r: %.1f GPa' % (E_r / units.GPa)) assert (abs(E_r - E)/units.GPa < 1e-3) nu_r = -S_r[1,2]/S_r[1,1] print('Possion ratio from C_r: %.3f' % (nu_r))
params.crack_direction, params.cleavage_plane, params.crack_front ] print_crack_system(directions) # now, we build system aligned with requested crystallographic orientation unit_slab = Diamond(directions=directions, size=(1, 1, 1), symbol='Si', pbc=True, latticeconstant=a0) if (hasattr(params, 'check_rotated_elastic_constants') and # Check that elastic constants of the rotated system # lead to same Young's modulus and Poisson ratio params.check_rotated_elastic_constants): unit_slab.set_calculator(params.calc) C_r1 = measure_triclinic_elastic_constants(unit_slab, optimizer=FIRE, fmax=params.bulk_fmax) R = np.array([np.array(x) / np.linalg.norm(x) for x in directions]) C_r2 = rotate_elastic_constants(C, R) for C_r in [C_r1, C_r2]: S_r = np.linalg.inv(C_r) E_r = 1. / S_r[1, 1] print('Young\'s modulus from C_r: %.1f GPa' % (E_r / units.GPa)) assert (abs(E_r - E) / units.GPa < 1e-3) nu_r = -S_r[1, 2] / S_r[1, 1] print('Possion ratio from C_r: %.3f' % (nu_r))
cell.a = ase_atom.cell 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 # E.g. gamma-point SCF calculation can be set to mf_class = pbcdft.RKS # SCF with k-point sampling can be set to mf_class = lambda cell: pbcdft.KRKS(cell, kpts=cell.make_kpts([2, 2, 2])) 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)
class TestFitElasticConstants(matscipytest.MatSciPyTestCase): """ Tests of elastic constant calculation. We test with a cubic Silicon lattice, since this also has most of the symmetries of the lower-symmetry crystal families """ def setUp(self): self.pot = quippy.Potential('IP SW', param_str=""" <SW_params n_types="2" label="PRB_31_plus_H"> <comment> Stillinger and Weber, Phys. Rev. B 31 p 5262 (1984), extended for other elements </comment> <per_type_data type="1" atomic_num="1" /> <per_type_data type="2" atomic_num="14" /> <per_pair_data atnum_i="1" atnum_j="1" AA="0.0" BB="0.0" p="0" q="0" a="1.0" sigma="1.0" eps="0.0" /> <per_pair_data atnum_i="1" atnum_j="14" AA="8.581214" BB="0.0327827" p="4" q="0" a="1.25" sigma="2.537884" eps="2.1672" /> <per_pair_data atnum_i="14" atnum_j="14" AA="7.049556277" BB="0.6022245584" p="4" q="0" a="1.80" sigma="2.0951" eps="2.1675" /> <!-- triplet terms: atnum_c is the center atom, neighbours j and k --> <per_triplet_data atnum_c="1" atnum_j="1" atnum_k="1" lambda="21.0" gamma="1.20" eps="2.1675" /> <per_triplet_data atnum_c="1" atnum_j="1" atnum_k="14" lambda="21.0" gamma="1.20" eps="2.1675" /> <per_triplet_data atnum_c="1" atnum_j="14" atnum_k="14" lambda="21.0" gamma="1.20" eps="2.1675" /> <per_triplet_data atnum_c="14" atnum_j="1" atnum_k="1" lambda="21.0" gamma="1.20" eps="2.1675" /> <per_triplet_data atnum_c="14" atnum_j="1" atnum_k="14" lambda="21.0" gamma="1.20" eps="2.1675" /> <per_triplet_data atnum_c="14" atnum_j="14" atnum_k="14" lambda="21.0" gamma="1.20" eps="2.1675" /> </SW_params> """) self.fmax = 1e-4 self.at0 = Diamond('Si', latticeconstant=5.43) self.at0.set_calculator(self.pot) # relax initial positions and unit cell FIRE(StrainFilter(self.at0, mask=[1, 1, 1, 0, 0, 0]), logfile=None).run(fmax=self.fmax) self.C_ref = np.array( [[151.4276439, 76.57244456, 76.57244456, 0., 0., 0.], [76.57244456, 151.4276439, 76.57244456, 0., 0., 0.], [76.57244456, 76.57244456, 151.4276439, 0., 0., 0.], [0., 0., 0., 109.85498798, 0., 0.], [0., 0., 0., 0., 109.85498798, 0.], [0., 0., 0., 0., 0., 109.85498798]]) self.C_err_ref = np.array( [[1.73091718, 1.63682097, 1.63682097, 0., 0., 0.], [1.63682097, 1.73091718, 1.63682097, 0., 0., 0.], [1.63682097, 1.63682097, 1.73091718, 0., 0., 0.], [0., 0., 0., 1.65751232, 0., 0.], [0., 0., 0., 0., 1.65751232, 0.], [0., 0., 0., 0., 0., 1.65751232]]) self.C_ref_relaxed = np.array( [[151.28712587, 76.5394162, 76.5394162, 0., 0., 0.], [76.5394162, 151.28712587, 76.5394162, 0., 0., 0.], [76.5394162, 76.5394162, 151.28712587, 0., 0., 0.], [0., 0., 0., 56.32421772, 0., 0.], [0., 0., 0., 0., 56.32421772, 0.], [0., 0., 0., 0., 0., 56.32421772]]) self.C_err_ref_relaxed = np.array( [[1.17748661, 1.33333615, 1.33333615, 0., 0., 0.], [1.33333615, 1.17748661, 1.33333615, 0., 0., 0.], [1.33333615, 1.33333615, 1.17748661, 0., 0., 0.], [0., 0., 0., 0.18959684, 0., 0.], [0., 0., 0., 0., 0.18959684, 0.], [0., 0., 0., 0., 0., 0.18959684]]) def test_measure_triclinic_unrelaxed(self): # compare to brute force method without relaxation C = measure_triclinic_elastic_constants(self.at0, delta=1e-2, optimizer=None) self.assertArrayAlmostEqual(C / units.GPa, self.C_ref, tol=0.2) def test_measure_triclinic_relaxed(self): # compare to brute force method with relaxation C = measure_triclinic_elastic_constants(self.at0, delta=1e-2, optimizer=FIRE, fmax=self.fmax) self.assertArrayAlmostEqual(C / units.GPa, self.C_ref_relaxed, tol=0.2) def testcubic_unrelaxed(self): C, C_err = fit_elastic_constants(self.at0, 'cubic', verbose=False, graphics=False) self.assertArrayAlmostEqual(C / units.GPa, self.C_ref, tol=1e-2) if abs(C_err).max() > 0.: self.assertArrayAlmostEqual(C_err / units.GPa, self.C_err_ref, tol=1e-2) def testcubic_relaxed(self): C, C_err = fit_elastic_constants(self.at0, 'cubic', optimizer=FIRE, fmax=self.fmax, verbose=False, graphics=False) self.assertArrayAlmostEqual(C / units.GPa, self.C_ref_relaxed, tol=1e-2) if abs(C_err).max() > 0.: self.assertArrayAlmostEqual(C_err / units.GPa, self.C_err_ref_relaxed, tol=1e-2) def testorthorhombic_unrelaxed(self): C, C_err = fit_elastic_constants(self.at0, 'orthorhombic', verbose=False, graphics=False) self.assertArrayAlmostEqual(C / units.GPa, self.C_ref, tol=0.1) def testorthorhombic_relaxed(self): C, C_err = fit_elastic_constants(self.at0, 'orthorhombic', optimizer=FIRE, fmax=self.fmax, verbose=False, graphics=False) self.assertArrayAlmostEqual(C / units.GPa, self.C_ref_relaxed, tol=0.1) def testmonoclinic_unrelaxed(self): C, C_err = fit_elastic_constants(self.at0, 'monoclinic', verbose=False, graphics=False) self.assertArrayAlmostEqual(C / units.GPa, self.C_ref, tol=0.2) def testmonoclinic_relaxed(self): C, C_err = fit_elastic_constants(self.at0, 'monoclinic', optimizer=FIRE, fmax=self.fmax, verbose=False, graphics=False) self.assertArrayAlmostEqual(C / units.GPa, self.C_ref_relaxed, tol=0.2) def testtriclinic_unrelaxed(self): C, C_err = fit_elastic_constants(self.at0, 'triclinic', verbose=False, graphics=False) self.assertArrayAlmostEqual(C / units.GPa, self.C_ref, tol=0.2) def testtriclinic_relaxed(self): C, C_err = fit_elastic_constants(self.at0, 'triclinic', optimizer=FIRE, fmax=self.fmax, verbose=False, graphics=False) self.assertArrayAlmostEqual(C / units.GPa, self.C_ref_relaxed, tol=0.2)
# Now let's create a calculator from builtin models: calculator = my_torchani.models.ANI1ccx().ase() # .. note:: # Regardless of the dtype you use in your model, when converting it to ASE # calculator, it always automatically the dtype to ``torch.float64``. The # reason for this behavior is, at many cases, the rounding error is too # large for structure minimization. If you insist on using # ``torch.float32``, do the following instead: # # .. code-block:: python # # calculator = torchani.models.ANI1ccx().ase(dtype=torch.float32) # Now let's set the calculator for ``atoms``: atoms.set_calculator(calculator) # Now let's minimize the structure: print("Begin minimizing...") opt = BFGS(atoms) opt.run(fmax=0.001) print() # Now create a callback function that print interesting physical quantities: def printenergy(a=atoms): """Function to print the potential, kinetic and total energy.""" epot = a.get_potential_energy() / len(a) ekin = a.get_kinetic_energy() / len(a) print('Energy per atom: Epot = %.3feV Ekin = %.3feV (T=%3.0fK) ' 'Etot = %.3feV' % (epot, ekin, ekin / (1.5 * units.kB), epot + ekin))
cell.a=ase_atom.cell 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 # E.g. gamma-point SCF calculation can be set to mf_class = pbcdft.RKS # SCF with k-point sampling can be set to mf_class = lambda cell: pbcdft.KRKS(cell, kpts=cell.make_kpts([2,2,2])) 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()
from ase.lattice.cubic import Diamond from ase.md.velocitydistribution import MaxwellBoltzmannDistribution from ase.md.verlet import VelocityVerlet from ase import units size = 3 # Set up a crystal atoms = Diamond(directions=[[1, 0, 0], [0, 1, 0], [0, 0, 1]], symbol='Si', size=(size, size, size), pbc=True) # Describe the interatomic interactions with the Effective Medium Theory atoms.set_calculator(lammps['ref']) np.random.seed(42) # Set the momenta corresponding to T=300K MaxwellBoltzmannDistribution(atoms, 1000 * units.kB) # We want to run MD with constant energy using the VelocityVerlet algorithm. dyn = VelocityVerlet(atoms, 1 * units.fs) # 5 fs time step. def printenergy(a): """Function to print the potential, kinetic and total energy""" epot = a.get_potential_energy() / len(a) ekin = a.get_kinetic_energy() / len(a) delta = np.max(np.abs(a.get_forces() - lammps['our'].get_forces(a))) print('Energy per atom: Epot = %.3feV Ekin = %.3feV (T=%3.0fK) '
# set of utility routines specific this this model/testing framework from utilities import relax_atoms, relax_atoms_cell # the current model import model a0 = 5.44 # initial guess at lattice constant, cell will be relaxed below fmax = 0.01 # maximum force following relaxtion [eV/A] if not hasattr(model, 'bulk_reference'): # set up the a bulk = Diamond(symbol='Si', latticeconstant=a0) # specify that we will use model.calculator to compute forces, energies and stresses bulk.set_calculator(model.calculator) # use one of the routines from utilities module to relax the initial # unit cell and atomic positions bulk = relax_atoms_cell(bulk, tol=fmax, traj_file=None) else: bulk = model.bulk_reference.copy() bulk.set_calculator(model.calculator) a0 = bulk.cell[0, 0] # get lattice constant from relaxed bulk print "got a0 ", a0 bulk = Diamond(symbol="Si", latticeconstant=a0, directions=[[1, -1, 0], [1, 0, -1], [1, 1, 1]]) bulk.set_calculator(model.calculator)
from utilities import relax_atoms, relax_atoms_cell # the current model import model np.random.seed(75) a0 = 5.44 fmax = 0.01 # maximum force following relaxtion [eV/A] if not hasattr(model, 'bulk_reference'): # set up the a bulk = Diamond(symbol='Si', latticeconstant=a0) # specify that we will use model.calculator to compute forces, energies and stresses bulk.set_calculator(model.calculator) # use one of the routines from utilities module to relax the initial # unit cell and atomic positions bulk = relax_atoms_cell(bulk, tol=fmax, traj_file=None) else: bulk = model.bulk_reference.copy() bulk.set_calculator(model.bulk_reference.calc) print "BOB doing bulk pot en" e0 = bulk.get_potential_energy()/float(len(bulk)) print "got e0 ", e0 def interface_energy(e0, filename):
class TestFitElasticConstants(matscipytest.MatSciPyTestCase): """ Tests of elastic constant calculation. We test with a cubic Silicon lattice, since this also has most of the symmetries of the lower-symmetry crystal families """ def setUp(self): self.pot = quippy.Potential('IP SW', param_str=""" <SW_params n_types="2" label="PRB_31_plus_H"> <comment> Stillinger and Weber, Phys. Rev. B 31 p 5262 (1984), extended for other elements </comment> <per_type_data type="1" atomic_num="1" /> <per_type_data type="2" atomic_num="14" /> <per_pair_data atnum_i="1" atnum_j="1" AA="0.0" BB="0.0" p="0" q="0" a="1.0" sigma="1.0" eps="0.0" /> <per_pair_data atnum_i="1" atnum_j="14" AA="8.581214" BB="0.0327827" p="4" q="0" a="1.25" sigma="2.537884" eps="2.1672" /> <per_pair_data atnum_i="14" atnum_j="14" AA="7.049556277" BB="0.6022245584" p="4" q="0" a="1.80" sigma="2.0951" eps="2.1675" /> <!-- triplet terms: atnum_c is the center atom, neighbours j and k --> <per_triplet_data atnum_c="1" atnum_j="1" atnum_k="1" lambda="21.0" gamma="1.20" eps="2.1675" /> <per_triplet_data atnum_c="1" atnum_j="1" atnum_k="14" lambda="21.0" gamma="1.20" eps="2.1675" /> <per_triplet_data atnum_c="1" atnum_j="14" atnum_k="14" lambda="21.0" gamma="1.20" eps="2.1675" /> <per_triplet_data atnum_c="14" atnum_j="1" atnum_k="1" lambda="21.0" gamma="1.20" eps="2.1675" /> <per_triplet_data atnum_c="14" atnum_j="1" atnum_k="14" lambda="21.0" gamma="1.20" eps="2.1675" /> <per_triplet_data atnum_c="14" atnum_j="14" atnum_k="14" lambda="21.0" gamma="1.20" eps="2.1675" /> </SW_params> """) self.fmax = 1e-4 self.at0 = Diamond('Si', latticeconstant=5.43) self.at0.set_calculator(self.pot) # relax initial positions and unit cell FIRE(StrainFilter(self.at0, mask=[1,1,1,0,0,0]), logfile=None).run(fmax=self.fmax) self.C_ref = np.array([[ 151.4276439 , 76.57244456, 76.57244456, 0. , 0. , 0. ], [ 76.57244456, 151.4276439 , 76.57244456, 0. , 0. , 0. ], [ 76.57244456, 76.57244456, 151.4276439 , 0. , 0. , 0. ], [ 0. , 0. , 0. , 109.85498798, 0. , 0. ], [ 0. , 0. , 0. , 0. , 109.85498798, 0. ], [ 0. , 0. , 0. , 0. , 0. , 109.85498798]]) self.C_err_ref = np.array([[ 1.73091718, 1.63682097, 1.63682097, 0. , 0. , 0. ], [ 1.63682097, 1.73091718, 1.63682097, 0. , 0. , 0. ], [ 1.63682097, 1.63682097, 1.73091718, 0. , 0. , 0. ], [ 0. , 0. , 0. , 1.65751232, 0. , 0. ], [ 0. , 0. , 0. , 0. , 1.65751232, 0. ], [ 0. , 0. , 0. , 0. , 0. , 1.65751232]]) self.C_ref_relaxed = np.array([[ 151.28712587, 76.5394162 , 76.5394162 , 0. , 0. , 0. ], [ 76.5394162 , 151.28712587, 76.5394162 , 0. , 0. , 0. ], [ 76.5394162 , 76.5394162 , 151.28712587, 0. , 0. , 0. ], [ 0. , 0. , 0. , 56.32421772, 0. , 0. ], [ 0. , 0. , 0. , 0. , 56.32421772, 0. ], [ 0. , 0. , 0. , 0. , 0. , 56.32421772]]) self.C_err_ref_relaxed = np.array([[ 1.17748661, 1.33333615, 1.33333615, 0. , 0. , 0. ], [ 1.33333615, 1.17748661, 1.33333615, 0. , 0. , 0. ], [ 1.33333615, 1.33333615, 1.17748661, 0. , 0. , 0. ], [ 0. , 0. , 0. , 0.18959684, 0. , 0. ], [ 0. , 0. , 0. , 0. , 0.18959684, 0. ], [ 0. , 0. , 0. , 0. , 0. , 0.18959684]]) def test_measure_triclinic_unrelaxed(self): # compare to brute force method without relaxation C = measure_triclinic_elastic_constants(self.at0, delta=1e-2, optimizer=None) self.assertArrayAlmostEqual(C/units.GPa, self.C_ref, tol=0.2) def test_measure_triclinic_relaxed(self): # compare to brute force method with relaxation C = measure_triclinic_elastic_constants(self.at0, delta=1e-2, optimizer=FIRE, fmax=self.fmax) self.assertArrayAlmostEqual(C/units.GPa, self.C_ref_relaxed, tol=0.2) def testcubic_unrelaxed(self): C, C_err = fit_elastic_constants(self.at0, 'cubic', verbose=False, graphics=False) self.assertArrayAlmostEqual(C/units.GPa, self.C_ref, tol=1e-2) if abs(C_err).max() > 0.: self.assertArrayAlmostEqual(C_err/units.GPa, self.C_err_ref, tol=1e-2) def testcubic_relaxed(self): C, C_err = fit_elastic_constants(self.at0, 'cubic', optimizer=FIRE, fmax=self.fmax, verbose=False, graphics=False) self.assertArrayAlmostEqual(C/units.GPa, self.C_ref_relaxed, tol=1e-2) if abs(C_err).max() > 0.: self.assertArrayAlmostEqual(C_err/units.GPa, self.C_err_ref_relaxed, tol=1e-2) def testorthorhombic_unrelaxed(self): C, C_err = fit_elastic_constants(self.at0, 'orthorhombic', verbose=False, graphics=False) self.assertArrayAlmostEqual(C/units.GPa, self.C_ref, tol=0.1) def testorthorhombic_relaxed(self): C, C_err = fit_elastic_constants(self.at0, 'orthorhombic', optimizer=FIRE, fmax=self.fmax, verbose=False, graphics=False) self.assertArrayAlmostEqual(C/units.GPa, self.C_ref_relaxed, tol=0.1) def testmonoclinic_unrelaxed(self): C, C_err = fit_elastic_constants(self.at0, 'monoclinic', verbose=False, graphics=False) self.assertArrayAlmostEqual(C/units.GPa, self.C_ref, tol=0.2) def testmonoclinic_relaxed(self): C, C_err = fit_elastic_constants(self.at0, 'monoclinic', optimizer=FIRE, fmax=self.fmax, verbose=False, graphics=False) self.assertArrayAlmostEqual(C/units.GPa, self.C_ref_relaxed, tol=0.2) def testtriclinic_unrelaxed(self): C, C_err = fit_elastic_constants(self.at0, 'triclinic', verbose=False, graphics=False) self.assertArrayAlmostEqual(C/units.GPa, self.C_ref, tol=0.2) def testtriclinic_relaxed(self): C, C_err = fit_elastic_constants(self.at0, 'triclinic', optimizer=FIRE, fmax=self.fmax, verbose=False, graphics=False) self.assertArrayAlmostEqual(C/units.GPa, self.C_ref_relaxed, tol=0.2)