def test_frozen(self): """Base tests for FrozenPhonon""" filename = abidata.ref_file("trf2_5.out_PHBST.nc") phbands = PhononBands.from_file(filename) qpt_frac_coords = [0.5, 0.5, 0.5] fp = FrozenPhonon.from_phbands(phbands, qpt_frac_coords, 0 , etas=[-0.2, -0.1, 0, 0.1, 0.2], max_supercell=[5,5,5]) self.assertArrayEqual(fp.scale_matrix, [[-1, 0, 1], [-1, 1, 0], [-1, -1, 0]]) w = phbands.phfreqs[phbands.qindex(qpt_frac_coords), 0] energies = [0.0704, 0.0176, 0. , 0.0175, 0.0703] with self.assertRaises(ValueError): fp.energies = energies[:3] fp.energies = energies assert fp.ieta0 == 2 assert fp.n_displ == 5 fit_data = fp.fit_to_frequency() self.assertAlmostEqual(w, fit_data.freq, places=5) fit_data = fp.fit_to_frequency(min_fit_eta=-0.15, max_fit_eta=0.15) self.assertNotAlmostEqual(w, fit_data.freq, places=5) self.assertArrayAlmostEqual(fp.qpt_cart_coords, [0.55954285702497808, 0.55954285702497808, 0.55954285702497808]) if self.has_matplotlib(): assert fp.plot_fit_energies(freq=w, show=False) assert fp.plot_anharmonic_contribution(freq=w, show=False) assert fp.plot_anharmonic_contribution(freq=w, relative=True, show=False)
def setUpClass(cls): cls.strains = [-4, -2, 0, 2, 4, 6] path = os.path.join(abidata.dirpath, "refs", "si_qha") cls.gsr_paths = [os.path.join(path, "mp-149_{:+d}_GSR.nc".format(s)) for s in cls.strains] cls.dos_paths = [os.path.join(path, "mp-149_{:+d}_PHDOS.nc".format(s)) for s in cls.strains] cls.phbs = [PhononBands.from_file(os.path.join(path, "mp-149_{:+d}_PHBST.nc".format(s))) for s in cls.strains[2:4]]
def test_base(self): """Testing DielectricTensor""" anaddbnc_fname = abidata.ref_file("AlAs_nl_dte_anaddb.nc") phbstnc_fname = abidata.ref_file("AlAs_nl_dte_PHBST.nc") d = DielectricTensorGenerator.from_files(phbstnc_fname, anaddbnc_fname) assert d.eps0.shape == (3, 3) df = d.epsinf.get_dataframe() assert d.epsinf._repr_html_() repr(d); str(d) assert d.to_string(verbose=2) df = d.get_oscillator_dataframe(reim="all", tol=1e-8) df = d.get_oscillator_dataframe(reim="im", tol=1e-8) df = d.get_oscillator_dataframe(reim="re", tol=1e-8) self.assertAlmostEqual(d.tensor_at_frequency(0.001, units='Ha', gamma_ev=0.0)[0, 0], 11.917178540635028) d = DielectricTensorGenerator.from_objects(PhononBands.from_file(phbstnc_fname), AnaddbNcFile.from_file(anaddbnc_fname)) self.assertAlmostEqual(d.tensor_at_frequency(0.001, units='Ha', gamma_ev=0.0)[0, 0], 11.917178540635028) if self.has_matplotlib(): assert d.plot_vs_w(w_min=0.0001, w_max=0.01, num=10, units="Ha", show=False) assert d.plot_vs_w(w_min=0, w_max=None, num=10, units="cm-1", show=False) for comp in ["diag", "all", "diag_av"]: assert d.plot_vs_w(num=10, component=comp, units="cm-1", show=False)
def test_base(self): """Testing DielectricTensor""" anaddbnc_fname = abidata.ref_file("AlAs_nl_dte_anaddb.nc") phbstnc_fname = abidata.ref_file("AlAs_nl_dte_PHBST.nc") d = DielectricTensorGenerator.from_files(phbstnc_fname, anaddbnc_fname) repr(d) str(d) self.assertAlmostEqual( d.tensor_at_frequency(0.001, units='Ha')[0, 0], 11.917178540635028) d = DielectricTensorGenerator.from_objects( PhononBands.from_file(phbstnc_fname), AnaddbNcFile.from_file(anaddbnc_fname)) self.assertAlmostEqual( d.tensor_at_frequency(0.001, units='Ha')[0, 0], 11.917178540635028) if self.has_matplotlib(): assert d.plot_vs_w(w_min=0.0001, w_max=0.01, num=10, units="Ha", show=False) assert d.plot_vs_w(w_min=0, w_max=None, num=10, units="cm-1", show=False) for comp in ["diag", "all", "diag_av"]: assert d.plot_vs_w(num=10, component=comp, units="cm-1", show=False)
def test_base(self): """Base tests for PhononBands""" filename = abidata.ref_file("trf2_5.out_PHBST.nc") phbands = PhononBands.from_file(filename) print(phbands) assert PhononBands.as_phbands(phbands) is phbands assert np.array_equal( PhononBands.as_phbands(filename).phfreqs, phbands.phfreqs) self.serialize_with_pickle(phbands, protocols=[-1], test_eq=False) self.assertEqual(phbands.minfreq, 0.0) #self.assertEqual(phbands.maxfreq, 30) # Test XYZ vib _, filename = tempfile.mkstemp(text=True) phbands.create_xyz_vib(iqpt=0, filename=filename, max_supercell=[4, 4, 4]) # Test convertion to eigenvectors. Verify that they are orthonormal # Allow relatively large tolerance due to possible mismatching in the atomic masses between abinit and pmg eig = phbands.dyn_mat_eigenvect self.assertTrue( np.allclose(np.dot(eig[0], eig[0].T), np.eye(len(eig[0]), dtype=np.complex), atol=1e-5, rtol=1e-3))
def setUpClass(cls): cls.strains = [-4, -2, 0, 2, 4, 6] dirpath = os.path.join(abidata.dirpath, "refs", "si_qha") cls.gsr_paths = [os.path.join(dirpath, "mp-149_{:+d}_GSR.nc".format(s)) for s in cls.strains] cls.dos_paths = [os.path.join(dirpath, "mp-149_{:+d}_PHDOS.nc".format(s)) for s in cls.strains] cls.ddb_paths = [os.path.join(dirpath, "mp-149_{:+d}_DDB".format(s)) for s in cls.strains] cls.phbs_list = [PhononBands.from_file(os.path.join(dirpath, "mp-149_{:+d}_PHBST.nc".format(s))) for s in cls.strains[2:4]]
def test_base(self): """Base tests for PhononBands""" filename = abidata.ref_file("trf2_5.out_PHBST.nc") phbands = PhononBands.from_file(filename) print(phbands) assert PhononBands.as_phbands(phbands) is phbands assert np.array_equal( PhononBands.as_phbands(filename).phfreqs, phbands.phfreqs) self.serialize_with_pickle(phbands, protocols=[-1], test_eq=False) self.assertEqual(phbands.minfreq, 0.0) #self.assertEqual(phbands.maxfreq, 30) # Test XYZ vib phbands.create_xyz_vib(iqpt=0, filename=self.get_tmpname(text=True), max_supercell=[4, 4, 4]) # Test ascii file phbands.create_ascii_vib(iqpts=0, filename=self.get_tmpname(text=True), pre_factor=1) # Test phononwebsite file phbands.create_phononwebsite_json(filename=self.get_tmpname(text=True), name='test') # Test xmgrace phbands.to_xmgrace(self.get_tmpname(text=True)) # Test convertion to eigenvectors. Verify that they are orthonormal # Allow relatively large tolerance due to possible mismatching in the atomic masses between abinit and pmg eig = phbands.dyn_mat_eigenvect assert np.allclose(np.dot(eig[0], eig[0].T), np.eye(len(eig[0]), dtype=np.complex), atol=1e-5, rtol=1e-3) if self.has_matplotlib(): phbands.plot(show=False) phbands.plot_fatbands(show=False) phbands.plot_colored_matched(show=False) # Cannot compute PHDOS with q-path with self.assertRaises(ValueError): phdos = phbands.get_phdos() # convert to pymatgen object phbands.to_pymatgen()
def test_base(self): """Base tests for PhononBands""" filename = abidata.ref_file("trf2_5.out_PHBST.nc") phbands = PhononBands.from_file(filename) print(phbands) self.serialize_with_pickle(phbands, protocols=[-1], test_eq=False) self.assertEqual(phbands.minfreq, 0.0) #self.assertEqual(phbands.maxfreq, 30) # Test XYZ vib _, filename = tempfile.mkstemp(text=True) phbands.create_xyz_vib(iqpt=0, filename=filename, max_supercell=[4,4,4])
def test_base(self): """Base tests for PhononBands""" filename = abidata.ref_file("trf2_5.out_PHBST.nc") phbands = PhononBands.from_file(filename) print(phbands) self.serialize_with_pickle(phbands, protocols=[-1], test_eq=False) self.assertEqual(phbands.minfreq, 0.0) #self.assertEqual(phbands.maxfreq, 30) # Test XYZ vib _, filename = tempfile.mkstemp(text=True) phbands.create_xyz_vib(iqpt=0, filename=filename, max_supercell=[4, 4, 4])
def test_frozen(self): """Base tests for FrozenPhonon""" filename = abidata.ref_file("trf2_5.out_PHBST.nc") phbands = PhononBands.from_file(filename) qpt_frac_coords = [0.5, 0.5, 0.5] fp = FrozenPhonon.from_phbands(phbands, qpt_frac_coords, 0, etas=[-0.2, -0.1, 0, 0.1, 0.2], max_supercell=[5, 5, 5]) self.assertArrayEqual(fp.scale_matrix, [[-1, 0, 1], [-1, 1, 0], [-1, -1, 0]]) w = phbands.phfreqs[phbands.qindex(qpt_frac_coords), 0] energies = [0.0704, 0.0176, 0., 0.0175, 0.0703] with self.assertRaises(ValueError): fp.energies = energies[:3] fp.energies = energies assert fp.ieta0 == 2 assert fp.n_displ == 5 fit_data = fp.fit_to_frequency() self.assertAlmostEqual(w, fit_data.freq, places=5) fit_data = fp.fit_to_frequency(min_fit_eta=-0.15, max_fit_eta=0.15) self.assertNotAlmostEqual(w, fit_data.freq, places=5) self.assertArrayAlmostEqual( fp.qpt_cart_coords, [0.55954285702497808, 0.55954285702497808, 0.55954285702497808]) if self.has_matplotlib(): assert fp.plot_fit_energies(freq=w, show=False) assert fp.plot_anharmonic_contribution(freq=w, show=False) assert fp.plot_anharmonic_contribution(freq=w, relative=True, show=False)
def test_base(self): """Base tests for PhononBands""" filename = abidata.ref_file("trf2_5.out_PHBST.nc") phbands = PhononBands.from_file(filename) print(phbands) self.serialize_with_pickle(phbands, protocols=[-1], test_eq=False) self.assertEqual(phbands.minfreq, 0.0) #self.assertEqual(phbands.maxfreq, 30) # Test XYZ vib _, filename = tempfile.mkstemp(text=True) phbands.create_xyz_vib(iqpt=0, filename=filename, max_supercell=[4,4,4]) # Test convertion to eigenvectors. Verify that they are orthonormal # Allow relatively large tolerance due to possible mismatching in the atomic masses between abinit and pmg eig = phbands.dyn_mat_eigenvect self.assertTrue(np.allclose(np.dot(eig[0], eig[0].T), np.eye(len(eig[0]), dtype=np.complex), atol=1e-5, rtol=1e-3))
# The PHDOS.nc files can be obtained from the DDB used ddb.anaget_phbst_and_phdos_files(...) qha = QHA.from_files(gsr_paths, dos_paths) # To change the default EOS (vinet), use #qha.set_eos("murnaghan") qha.plot_energies(title="Energies as a function of volume for different T") qha.plot_thermal_expansion_coeff( title="Thermal expansion coefficient as a function of T") qha.plot_vol_vs_t(title="Volume as a function of T") # Fake temperatures to test the plotting function. phbs_list = [ PhononBands.from_file( os.path.join(dirpath, "mp-149_{:+d}_PHBST.nc".format(s))) for s in strains[2:4] ] qha.plot_phbs(phbs_list, temperatures=[10, 20], title="Phonon band structures with color depending on T") # Here we build a Phonopy QHA object. # Cannot run this code because it breaks sphinx-gallery #qha_phonopy = qha.get_phonopy_qha(tstop=500, num=11) #qha_phonopy.run() #qha_phonopy.plot_bulk_modulus_temperature().show()
def test_base(self): """Base tests for PhononBands""" filename = abidata.ref_file("trf2_5.out_PHBST.nc") phbands = PhononBands.from_file(filename) repr(phbands); str(phbands) assert phbands.to_string(title="Title", with_structure=False, with_qpoints=True, verbose=1) assert PhononBands.as_phbands(phbands) is phbands with self.assertRaises(TypeError): PhononBands.as_phbands({}) assert np.array_equal(PhononBands.as_phbands(filename).phfreqs, phbands.phfreqs) with abilab.abiopen(abidata.ref_file("trf2_5.out_PHBST.nc")) as nc: repr(nc); str(nc) assert nc.to_string(verbose=1) assert nc.params["nqpt"] == len(nc.qpoints) assert nc.qpoints.is_path assert any(q.name is not None for q in nc.qpoints) same_phbands_nc = PhononBands.as_phbands(nc) self.assert_equal(same_phbands_nc.phfreqs, phbands.phfreqs) assert phbands.phdispl_cart.shape == (phbands.nqpt, phbands.num_branches, phbands.num_branches) # a + b gives plotter assert hasattr(same_phbands_nc + phbands, "combiplot") self.serialize_with_pickle(phbands, protocols=[-1], test_eq=False) # From pickle file. tmp_path = self.get_tmpname(suffix=".pickle") with open(tmp_path, "wb") as fh: pickle.dump(phbands, fh) same_phbands = PhononBands.as_phbands(tmp_path) self.assert_equal(same_phbands.phfreqs, phbands.phfreqs) # a + b + c gives plotter p = phbands + same_phbands + same_phbands_nc assert hasattr(p, "combiplot") assert phbands.minfreq == 0.0 #self.assertEqual(phbands.maxfreq, 30) assert phbands.phfactor_ev2units("eV") == abu.phfactor_ev2units("eV") # Test XYZ vib phbands.create_xyz_vib(iqpt=0, filename=self.get_tmpname(text=True), max_supercell=[4, 4, 4]) # Test ascii file phbands.create_ascii_vib(iqpts=0, filename=self.get_tmpname(text=True), pre_factor=1) # Test phononwebsite file phbands.create_phononwebsite_json(filename=self.get_tmpname(text=True), name='test') assert phbands.view_phononwebsite(verbose=1, dryrun=True) == 0 # Test xmgrace phbands.to_xmgrace(self.get_tmpname(text=True)) #phbands.to_xmgrace(sys.stdout) df = phbands.get_dataframe() assert "freq" in df and "mode" in df self.assert_almost_equal(df["freq"].values.min(), 0) umodes = phbands.get_unstable_modes(below_mev=-1000) assert len(umodes) == 0 acoustic_modes = phbands.acoustic_indices((0, 0, 0)) self.assertArrayEqual(acoustic_modes, [0, 1, 2]) asr_breaking = phbands.asr_breaking() assert asr_breaking.absmax_break == 0 # Test convertion to eigenvectors. Verify that they are orthonormal # Allow relatively large tolerance due to possible mismatching in the atomic masses between abinit and pmg # (Note that amu is None here) assert phbands.amu is None eig = phbands.dyn_mat_eigenvect assert len(eig) == phbands.nqpt cidentity = np.eye(len(eig[0]), dtype=np.complex) for iq in range(len(eig)): #print("About to test iq", iq, np.dot(eig[iq], eig[iq].T)) #assert np.allclose(np.dot(eig[iq], eig[iq].T), cidentity , atol=1e-5, rtol=1e-3) assert np.allclose(np.dot(eig[iq].conjugate().T, eig[iq]), cidentity , atol=1e-5, rtol=1e-3) #self.assert_almost_equal(np.dot(eig[iq].conjugate().T, eig[iq]), cidentity) # Mapping reduced coordinates -> labels qlabels = { (0,0,0): r"$\Gamma$", (0.375, 0.375, 0.75): "K", (0.5, 0.5, 1.0): "X", (0.5, 0.5, 0.5): "L", (0.5, 0.0, 0.5): "X", (0.5, 0.25, 0.75): "W", } if self.has_matplotlib(): assert phbands.plot(units="Thz", show=False) assert phbands.plot_fatbands(units="ha", qlabels=qlabels, show=False) assert phbands.plot_fatbands(phdos_file=abidata.ref_file("trf2_5.out_PHDOS.nc"), units="thz", show=False) assert phbands.plot_colored_matched(units="cm^-1", show=False) assert phbands.plot_phdispl(qpoint=(0, 0, 0), units="cm^-1", hatches=None, show=False) assert phbands.plot_phdispl(qpoint=(0, 0, 0), units="cm^-1", hatches=None, show=False, cart_dir="x+y") assert phbands.plot_phdispl(qpoint=(0, 0, 0), units="cm^-1", hatches=None, show=False, use_sqrt=True, normalize=False) with self.assertRaises(ValueError): # No LO-TO terms assert phbands.plot_phdispl(qpoint=1, is_non_analytical_direction=True, show=False) assert phbands.plot_phdispl_cartdirs(qpoint=0, units="cm^-1", show=False) assert phbands.boxplot(units="ev", mode_range=[2, 4], show=False) # Cannot compute PHDOS with q-path with self.assertRaises(ValueError): phdos = phbands.get_phdos() # convert to pymatgen object phbands.to_pymatgen() # get frozen phonons phbands.get_frozen_phonons((0.5, 0.5, 1.0), 1, eta=0.5, max_supercell=[5,5,5]) assert not phbands.has_linewidths phbands.linewidths = np.ones(phbands.shape) assert phbands.has_linewidths
def test_base(self): """Base tests for PhononBands""" filename = abidata.ref_file("trf2_5.out_PHBST.nc") phbands = PhononBands.from_file(filename) repr(phbands) str(phbands) assert phbands.to_string(title="Title", with_structure=False, with_qpoints=True, verbose=1) assert PhononBands.as_phbands(phbands) is phbands with self.assertRaises(TypeError): PhononBands.as_phbands({}) assert np.array_equal( PhononBands.as_phbands(filename).phfreqs, phbands.phfreqs) with abilab.abiopen(abidata.ref_file("trf2_5.out_PHBST.nc")) as nc: repr(nc) str(nc) assert nc.to_string(verbose=1) assert nc.params["nqpt"] == len(nc.qpoints) assert nc.qpoints.is_path assert any(q.name is not None for q in nc.qpoints) same_phbands_nc = PhononBands.as_phbands(nc) self.assert_equal(same_phbands_nc.phfreqs, phbands.phfreqs) assert phbands.phdispl_cart.shape == (phbands.nqpt, phbands.num_branches, phbands.num_branches) # a + b gives plotter assert hasattr(same_phbands_nc + phbands, "combiplot") assert phbands.epsinf is None and phbands.zcart is None self.serialize_with_pickle(phbands, protocols=[-1], test_eq=False) # From pickle file. tmp_path = self.get_tmpname(suffix=".pickle") with open(tmp_path, "wb") as fh: pickle.dump(phbands, fh) same_phbands = PhononBands.as_phbands(tmp_path) self.assert_equal(same_phbands.phfreqs, phbands.phfreqs) # a + b + c gives plotter p = phbands + same_phbands + same_phbands_nc assert hasattr(p, "combiplot") assert phbands.minfreq == 0.0 #self.assertEqual(phbands.maxfreq, 30) assert phbands.phfactor_ev2units("eV") == abu.phfactor_ev2units("eV") # Test XYZ vib phbands.create_xyz_vib(iqpt=0, filename=self.get_tmpname(text=True), max_supercell=[4, 4, 4]) # Test ascii file phbands.create_ascii_vib(iqpts=0, filename=self.get_tmpname(text=True), pre_factor=1) # Test phononwebsite file phbands.create_phononwebsite_json(filename=self.get_tmpname(text=True), name='test') assert phbands.view_phononwebsite(verbose=1, dryrun=True) == 0 # Test xmgrace phbands.to_xmgrace(self.get_tmpname(text=True)) #phbands.to_xmgrace(sys.stdout) df = phbands.get_dataframe() assert "freq" in df and "mode" in df self.assert_almost_equal(df["freq"].values.min(), 0) umodes = phbands.get_unstable_modes(below_mev=-1000) assert len(umodes) == 0 acoustic_modes = phbands.acoustic_indices((0, 0, 0)) self.assertArrayEqual(acoustic_modes, [0, 1, 2]) asr_breaking = phbands.asr_breaking() assert asr_breaking.absmax_break == 0 # Test convertion to eigenvectors. Verify that they are orthonormal # Allow relatively large tolerance due to possible mismatching in the atomic masses between abinit and pmg # (Note that amu is None here) assert phbands.amu is None eig = phbands.dyn_mat_eigenvect assert len(eig) == phbands.nqpt cidentity = np.eye(len(eig[0]), dtype=np.complex) for iq in range(len(eig)): #print("About to test iq", iq, np.dot(eig[iq], eig[iq].T)) #assert np.allclose(np.dot(eig[iq], eig[iq].T), cidentity , atol=1e-5, rtol=1e-3) assert np.allclose(np.dot(eig[iq].conjugate().T, eig[iq]), cidentity, atol=1e-5, rtol=1e-3) #self.assert_almost_equal(np.dot(eig[iq].conjugate().T, eig[iq]), cidentity) # Mapping reduced coordinates -> labels qlabels = { (0, 0, 0): r"$\Gamma$", (0.375, 0.375, 0.75): "K", (0.5, 0.5, 1.0): "X", (0.5, 0.5, 0.5): "L", (0.5, 0.0, 0.5): "X", (0.5, 0.25, 0.75): "W", } if self.has_matplotlib(): assert phbands.plot(units="Thz", show=False, temp=300) assert phbands.plot_fatbands(units="ha", qlabels=qlabels, show=False) assert phbands.plot_fatbands( phdos_file=abidata.ref_file("trf2_5.out_PHDOS.nc"), units="thz", show=False) assert phbands.plot_colored_matched(units="cm^-1", show=False) assert phbands.plot_phdispl(qpoint=(0, 0, 0), units="cm^-1", hatches=None, show=False) assert phbands.plot_phdispl(qpoint=(0, 0, 0), units="cm^-1", hatches=None, show=False, cart_dir="x+y") assert phbands.plot_phdispl(qpoint=(0, 0, 0), units="cm^-1", hatches=None, show=False, use_sqrt=True, normalize=False) with self.assertRaises(ValueError): # No LO-TO terms assert phbands.plot_phdispl(qpoint=1, is_non_analytical_direction=True, show=False) assert phbands.plot_phdispl_cartdirs(qpoint=0, units="cm^-1", show=False) assert phbands.boxplot(units="ev", mode_range=[2, 4], show=False) # Cannot compute PHDOS with q-path with self.assertRaises(ValueError): phdos = phbands.get_phdos() # convert to pymatgen object phbands.to_pymatgen() # get frozen phonons phbands.get_frozen_phonons((0.5, 0.5, 1.0), 1, eta=0.5, max_supercell=[5, 5, 5]) assert not phbands.has_linewidths phbands.linewidths = np.ones(phbands.shape) assert phbands.has_linewidths
def from_phbst(cls, phbst_path, ignore_neg_freqs=True, labels=None): """ Creates an instance of the object starting interpolating the acoustic frequencies from a PHBST netcdf file. The file should contain a series of directions starting from gamma and with the same number of points for each direction, as the one produced in the from_ddb method. Args: phbst_path: path to the PHBST netcdf file. ignore_neg_freqs (bool): if True points with negative frequencies will not be considered in the fit, in order to ignore inaccuracies in the long range behavior. labels (list): list of string with the name of the directions. Returns: an instance of SoundVelocity """ phb = PhononBands.from_file(phbst_path) structure = phb.structure rlatt = structure.lattice.reciprocal_lattice # q points in cartesian coordinate in 1/bohr, the original units are 1/A qpt_cart_coords = [ rlatt.get_cartesian_coords(c) * bohr_to_angstrom for c in phb.qpoints.frac_coords ] qpt_cart_norms = np.linalg.norm(qpt_cart_coords, axis=1) # find the indices of the gamma points gamma_ind = [] for i, q in enumerate(phb.qpoints.frac_coords): if np.array_equal(q, [0, 0, 0]): gamma_ind.append(i) n_directions = len(gamma_ind) n_points = len(phb.qpoints) / n_directions if not n_points.is_integer(): raise ValueError( 'Error extracting information from {}'.format(phbst_path)) n_points = int(n_points) phfreqs = phb.phfreqs eigdisp = phb.phdispl_cart sound_velocities = [] mode_types = [] directions = [] all_acoustic_freqs = [] all_qpts = [] for i in range(n_directions): start = n_points * i # index of the end point used for the slice # (the position of the last point is actually end-1) end = n_points * (i + 1) dir_freqs = phfreqs[start:end] dir_displ = eigdisp[start:end] # matching bands dir_eigv = get_dyn_mat_eigenvec(dir_displ, structure, amu=phb.amu) n_freqs = 3 * len(structure) ind_match = np.zeros((n_points, n_freqs), dtype=np.int) ind_match[0] = range(n_freqs) for j in range(1, n_points): k = j - 1 match = match_eigenvectors(dir_eigv[k], dir_eigv[j]) ind_match[j] = [match[m] for m in ind_match[k]] acoustic_freqs = (dir_freqs[np.arange(n_points)[:, None], ind_match])[:, 0:3] acoustic_displ = (dir_displ[np.arange(n_points)[:, None], ind_match])[:, 0:3] direction = phb.qpoints[end - 1].frac_coords direction = np.array(direction) / np.linalg.norm(direction) directions.append(direction) # identify the first (not gamma) qpoint with all positive frequencies first_positive_freq_ind = None for j in range(1, n_points): if min(acoustic_freqs[j]) > 0: first_positive_freq_ind = j break if first_positive_freq_ind is None or first_positive_freq_ind - n_points / 2 > 0: raise ValueError( "too many negative frequencies along direction {}".format( direction)) sv = [] mt = [] cart_versor = qpt_cart_coords[end - 1] / np.linalg.norm( qpt_cart_coords[end - 1]) for k in range(3): start_fit = 0 if ignore_neg_freqs and first_positive_freq_ind > 1: start_fit = first_positive_freq_ind slope, se, _, _ = np.linalg.lstsq( qpt_cart_norms[start + start_fit:end][:, np.newaxis], acoustic_freqs[start_fit:, k] * eV_to_Ha, rcond=None) sv.append(slope[0] * abu.velocity_at_to_si) # identify the type of the mode (longitudinal/transversal) based on the # scalar product between the eigendisplacement and the direction. disp_0 = acoustic_displ[first_positive_freq_ind + 1, k, 0:3] disp_0 = disp_0 / np.linalg.norm(disp_0) scalar_prod = np.abs(np.dot(disp_0, cart_versor)) if scalar_prod > 0.9: mt.append("longitudinal") elif scalar_prod < 0.1: mt.append("transversal") else: mt.append(None) # sort the lists based on the sound velocites sv, mt, freqs = zip(*sorted(zip(sv, mt, acoustic_freqs.T))) sound_velocities.append(sv) mode_types.append(mt) all_acoustic_freqs.append(freqs) all_qpts.append(phb.qpoints.frac_coords[start:end]) return cls(directions=directions, sound_velocities=sound_velocities, mode_types=mode_types, structure=structure, labels=labels, phfreqs=all_acoustic_freqs, qpts=all_qpts)