Пример #1
0
    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))
Пример #2
0
    def read_phbands_on_qpath(self):
        """
        Return a list of |PhononBands| computed at the different volumes.
        The ``iv0`` entry corresponds to the central point used to compute Grunesein parameters
        with finite differences. This object stores the Grunesein parameters in ``grun_vals``.
        """
        if "gruns_qpath" not in self.rootgrp.variables:
            cprint(
                "File `%s` does not contain phonon bands, returning empty list."
                % self.path, "yellow")
            return []

        qfrac_coords = self.read_value("gruns_qpath")
        grun_vals = self.read_value("gruns_gvals_qpath")
        freqs_vol = self.read_value("gruns_wvols_qpath") * abu.Ha_eV
        # TODO: Convert?
        dwdq_qpath = self.read_value("gruns_dwdq_qpath")

        amuz = self.read_amuz_dict()
        #print("amuz", amuz)

        # nctkarr_t("gruns_phdispl_cart_qpath", "dp", &
        # "two, number_of_phonon_modes, number_of_phonon_modes, gruns_nvols, gruns_nqpath") &
        # NOTE: in GRUNS the displacements are in Bohr. here we convert to Ang to be
        # consistent with the PhononBands API.
        phdispl_cart_qptsvol = self.read_value("gruns_phdispl_cart_qpath",
                                               cmode="c") * abu.Bohr_Ang

        lattices = self.read_value(
            "gruns_rprimd"
        ) * abu.Bohr_Ang  #, "dp", "three, three, gruns_nvols")
        gruns_xred = self.read_value(
            "gruns_xred")  #, "dp", "three, number_of_atoms, gruns_nvols")

        structures = self.read_structures()

        phbands_qpath_vol = []
        for ivol in range(self.num_volumes):
            structure = structures[ivol]
            # TODO non_anal_ph
            qpoints = Kpath(structure.reciprocal_lattice, qfrac_coords)
            phdispl_cart = phdispl_cart_qptsvol[:, ivol].copy()
            phb = PhononBands(structure,
                              qpoints,
                              freqs_vol[:, ivol],
                              phdispl_cart,
                              non_anal_ph=None,
                              amu=amuz)
            # Add Grunesein parameters.
            if ivol == self.iv0: phb.grun_vals = grun_vals
            phbands_qpath_vol.append(phb)

        return phbands_qpath_vol
Пример #3
0
    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()
Пример #4
0
    def read_phbands_on_qpath(self):
        """
        Return a list of |PhononBands| computed at the different volumes.
        The ``iv0`` entry corresponds to the central point used to compute Grunesein parameters
        with finite differences. This object stores the Grunesein parameters in ``grun_vals``.
        """
        if "gruns_qpath" not in self.rootgrp.variables:
            cprint("File `%s` does not contain phonon bands, returning empty list." % self.path, "yellow")
            return []

        qfrac_coords = self.read_value("gruns_qpath")
        grun_vals = self.read_value("gruns_gvals_qpath")
        freqs_vol = self.read_value("gruns_wvols_qpath") * abu.Ha_eV
        # TODO: Convert?
        dwdq_qpath = self.read_value("gruns_dwdq_qpath")

        amuz = self.read_amuz_dict()
        #print("amuz", amuz)

        # nctkarr_t("gruns_phdispl_cart_qpath", "dp", &
        # "two, number_of_phonon_modes, number_of_phonon_modes, gruns_nvols, gruns_nqpath") &
        # NOTE: in GRUNS the displacements are in Bohr. here we convert to Ang to be
        # consistent with the PhononBands API.
        phdispl_cart_qptsvol = self.read_value("gruns_phdispl_cart_qpath", cmode="c") * abu.Bohr_Ang

        lattices = self.read_value("gruns_rprimd") * abu.Bohr_Ang #, "dp", "three, three, gruns_nvols")
        gruns_xred = self.read_value("gruns_xred")                #, "dp", "three, number_of_atoms, gruns_nvols")

        phbands_qpath_vol = []
        for ivol in range(self.num_volumes):
            # TODO structure depends on:
            # volumes
            # non_anal_ph
            # amu: DONE
            # phdispl_cart DONE
            if ivol == self.iv0:
                structure = self.structure
            else:
                structure = self.structure.__class__(lattices[ivol], self.structure.species, gruns_xred[ivol])

            qpoints = Kpath(structure.reciprocal_lattice, qfrac_coords)
            phdispl_cart = phdispl_cart_qptsvol[:, ivol].copy()
            phb = PhononBands(structure, qpoints, freqs_vol[:, ivol], phdispl_cart, non_anal_ph=None, amu=amuz)
            # Add Grunesein parameters.
            if ivol == self.iv0: phb.grun_vals = grun_vals
            phbands_qpath_vol.append(phb)

        return phbands_qpath_vol
Пример #5
0
 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]]
Пример #6
0
    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)
Пример #7
0
    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)
Пример #8
0
    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)
Пример #9
0
 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]]
Пример #10
0
    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))
Пример #11
0
    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])
Пример #12
0
    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])
Пример #13
0
    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)
Пример #14
0
# 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()
Пример #15
0
    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
Пример #16
0
    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
Пример #17
0
    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)