def test_e_subclass_star(self): d = s.Direct((1,1,1),np.array([1,1,1])*np.pi/2) r = s.Reciprocal(np.array([1,1,1])*np.pi*2, np.array([1,1,1])*np.pi/2) self.assertTrue( d.isstar(r) ) self.assertTrue( r.isstar(d) ) self.assertEqual( d, r.star ) self.assertEqual( r, d.star )
def test_i_iron_self_consistency(self): """Test with data as iron spinwaves, but test only *at* grid points.""" d = s.Direct((2.87, 2.87, 2.87), np.pi/2*np.array((1, 1, 1)), "Im-3m") r = d.star bz = s.BrillouinZone(r) # constructs an irreducible Bz by default bzg = s.BZTrellisQdc(bz, 0.125) Q = bzg.rlu bzg.fill(fe_dispersion(Q), (1,), bzg.rlu, (0,3)) # The irreducible interpolation must be used here # since the Brillouin zone is an *irreducible* Brillouin zone!! intres, _ = bzg.ir_interpolate_at(Q, False, False) antres = fe_dispersion(Q) self.assertTrue(np.isclose(np.squeeze(intres), antres).all())
def test_aflow_crystaldatabase(self): tested = 0 failed = 0 errored = 0 failed_afl = [] failed_ratio = [] errored_afl = [] errored_arg = [] hall_groups_passed = np.zeros(530, dtype='int') hall_groups_failed = np.zeros(530, dtype='int') for afl in get_aflow_lattices(): # afl == [hall_number, basis_vector_lengths, basis_vector_angles, Hall_symbol] dlat = s.Direct(afl[1], afl[2], afl[3]) tested += 1 try: bz = s.BrillouinZone(dlat.star) vol_bz = bz.polyhedron.volume vol_ir = bz.ir_polyhedron.volume if not np.isclose(vol_ir, vol_bz / s.PointSymmetry(afl[0]).size): failed += 1 failed_afl.append(afl) failed_ratio.append(vol_ir / vol_bz * s.PointSymmetry(afl[0]).size) hall_groups_failed[afl[0] - 1] += 1 else: hall_groups_passed[afl[0] - 1] += 1 except Exception as err: errored += 1 errored_afl.append(afl) errored_arg.append(err.args) if failed > 0: print("\nFailed to find correct irreducible Brillouin zone for", failed, "out of", tested, "lattices") for file, rat in zip(failed_afl, failed_ratio): print(file, rat) if errored > 0: print("\nException raised for", errored, "out of", tested, "lattices") for file, arg in zip(errored_afl, errored_arg): print(file, arg) print("\nHall groups passed (total =", hall_groups_passed.sum(), "of", tested, "tested)") encoded_hgp = [n2chr(x) for x in hall_groups_passed] for x in [encoded_hgp[i * 53:(i + 1) * 53] for i in range(10)]: print(''.join(x)) self.assertTrue(failed == 0) self.assertTrue(errored == 0)
def make_dr(a, b, c, al=np.pi / 2, be=np.pi / 2, ga=np.pi / 2, hall=1): """Make a Direct and Reciprocal lattice from Direct lattice parameters.""" d = s.Direct(a, b, c, al, be, ga, hall) r = d.star return (d, r)
def test_nacl(self): # load numpy arrays from the compressed binary pack nacl = getLoad(np.load,'test_5_gamma.npz') # construct the NaCl direct lattice basis_vec = nacl['basis_vectors'] atom_pos = nacl['atom_positions'] atom_idx = nacl['atom_index'] dlat = s.Direct(basis_vec, atom_pos, atom_idx, 'P1') dlat.spacegroup = s.Symmetry(nacl['spacegroup_mat'],nacl['spacegroup_vec']) # use it to construct an irreducible Brillouin zone bz = s.BrillouinZone(dlat.star) # and use that to produce a hybrid interpolation grid # with parameters stored in the binary pack max_volume = float(nacl['grid_max_volume']) always_triangulate = bool(nacl['grid_always_triangulate']) grid = s.BZTrellisQdc(bz, max_volume, always_triangulate) # verify the stored grid points to ensure we have the same irreducible # wedge and grid self.assertTrue(np.allclose(grid.rlu, nacl['grid_rlu'])) # insert the Euphonic-derived eigenvalues and eigenvectors for the grid # points, which are used in the interpolation grid.fill( nacl['grid_values'], nacl['grid_values_elements'], nacl['grid_values_weights'], nacl['grid_vectors'], nacl['grid_vectors_elements'], nacl['grid_vectors_weights'], bool(nacl['grid_sort'])) # the fourth grid point is inside of the irreducible volume, which # ensures we avoid degeneracies q_ir = grid.rlu[4:5] # find all symmetry equivalent q within the first Brillouin zone by # applying each pointgroup operator to q_ir to find q_nu = R^T_nu q_ir q_nu = np.einsum('xji,aj->xi', dlat.pointgroup.W, q_ir) # The std::sort algorithm does not provide the same pointgroup sorting # on all systems, but there should be a permutation mapping: perm = np.array([np.squeeze(np.argwhere(np.all(np.isclose(q_nu,x),axis=1))) for x in nacl['q_nu']]) # The permutation must be complete and unique self.assertTrue(np.unique(perm).size == q_nu.shape[0]) # And the permuted q_nu must match the stored q_nu q_nu = q_nu[perm] self.assertTrue(np.allclose(q_nu, nacl['q_nu'])) # Use the grid to interpolate at each q_nu: br_val, br_vec = grid.ir_interpolate_at(q_nu) br_val = np.squeeze(br_val) # verify that q_ir does not have degeneracies: self.assertFalse(np.any(np.isclose(np.diff(br_val, axis=1), 0.))) # and that the 'interpolated' eigenvalues are identical for all q_nu self.assertTrue(np.allclose(np.diff(br_val, axis=0), 0.)) # plus that the interpolated eigenvalues match the store Euphonic eigenvalues self.assertTrue(np.allclose(br_val, nacl['euphonic_values'])) # convert the eigenvalues into the same cartesian coordinate system # used by Euphonic br_vec = np.einsum('ba,ijkb->ijka', basis_vec, br_vec) # load the Euphonic calculated eigenvectors eu_vec = nacl['euphonic_vectors'] # The 'interpolated' eigenvectors and the Euphonic eigenvectors should # only be equivalent up to an overall phase factor, so find it: antiphase = np.exp(-1J*np.angle(np.einsum('qmij,qmij->qm', np.conj(eu_vec), br_vec))) # and remove the phase from the interpolated eigenvectors br_vec = np.einsum('ab,abij->abij', antiphase, br_vec) # now all eigenvectors must match self.assertTrue(np.allclose(br_vec, eu_vec))