def test_factors(self): e = EnergyArray([27.21138386, 1], "eV").to("Ha") self.assertTrue(str(e) == "[ 0.99999996 0.03674932] Ha") l = LengthArray([1.0], "ang").to("bohr") self.assertTrue(str(l) == "[ 1.88972612] bohr") v = ArrayWithUnit([1, 2, 3], "bohr^3").to("ang^3") self.assertTrue(str(v) == '[ 0.14818471 0.29636942 0.44455413] ang^3')
def test_factors(self): e = EnergyArray([27.21138386, 1], "eV").to("Ha") self.assertTrue(str(e).endswith("Ha")) l = LengthArray([1.0], "ang").to("bohr") self.assertTrue(str(l).endswith(" bohr")) v = ArrayWithUnit([1, 2, 3], "bohr^3").to("ang^3") self.assertTrue(str(v).endswith(' ang^3'))
def test_array_algebra(self): ene_ha = EnergyArray([1, 2], "Ha") ene_ev = EnergyArray([1, 2], "eV") time_s = TimeArray([1, 2], "s") e1 = ene_ha.copy() e1 += 1 e2 = ene_ha.copy() e2 -= 1 e3 = ene_ha.copy() #e3 /= 2 e4 = ene_ha.copy() e4 *= 2 objects_with_unit = [ ene_ha + ene_ev, ene_ha - ene_ev, 3 * ene_ha, ene_ha * 3, ene_ha / 3, 3 / ene_ha, ene_ha * time_s, ene_ha / ene_ev, ene_ha.copy(), ene_ha[0:1], e1, e2, e3, e4, ] for i, obj in enumerate(objects_with_unit): #print(i, obj.unit) self.assertTrue(hasattr(obj, "unit")) #self.assertTrue(str(obj.unit) == "Ha") objects_without_unit = [ # Here we could return a FloatWithUnit object but I prefer this # a bare scalar since FloatWithUnit extends float while we could # have an int. ene_ha[0], ] for obj in objects_without_unit: self.assertFalse(hasattr(obj, "unit")) with self.assertRaises(UnitError): ene_ha + time_s
def test_energy(self): """ Similar to FloatWithUnitTest.test_energy. Check whether EnergyArray and FloatWithUnit have same behavior. # TODO One can merge the two tests easily: for obj in [Energy, EnergyArray]: a = obj(...) self.assert(...) """ a = EnergyArray(1.1, "eV") b = a.to("Ha") self.assertAlmostEqual(b, 0.0404242579378) c = EnergyArray(3.14, "J") self.assertAlmostEqual(c.to("eV"), 1.9598339337836966e+19) # self.assertRaises(ValueError, Energy, 1, "m") d = EnergyArray(1, "Ha") self.assertAlmostEqual(a + d, 28.31138386) self.assertAlmostEqual(a - d, -26.11138386) self.assertEqual(a + 1, 2.1)
def test_energy(self): """ Similar to FloatWithUnitTest.test_energy. Check whether EnergyArray and FloatWithUnit have same behavior. # TODO One can merge the two tests easily: for obj in [Energy, EnergyArray]: a = obj(...) self.assert(...) """ a = EnergyArray(1.1, "eV") b = a.to("Ha") self.assertAlmostEqual(float(b), 0.0404242579378) c = EnergyArray(3.14, "J") self.assertAlmostEqual(float(c.to("eV")), 1.959833865527343e+19, 5) # self.assertRaises(ValueError, Energy, 1, "m") d = EnergyArray(1, "Ha") self.assertAlmostEqual(float(a + d), 28.31138602063284) self.assertAlmostEqual(float(a - d), -26.111386020632835) self.assertEqual(float(a + 1), 2.1)
def read_phonons(self): """Read phonon frequencies from the output file.""" # # Phonon wavevector (reduced coordinates) : 0.00000 0.00000 0.00000 # Phonon energies in Hartree : # 1.089934E-04 4.990512E-04 1.239177E-03 1.572715E-03 1.576801E-03 # 1.579326E-03 # Phonon frequencies in cm-1 : # - 2.392128E+01 1.095291E+02 2.719679E+02 3.451711E+02 3.460677E+02 # - 3.466221E+02 BEGIN = " Phonon wavevector (reduced coordinates) :" END = " Phonon frequencies in cm-1 :" ph_tasks, qpts, phfreqs = self[1:], [], [] for task in ph_tasks: with open(task.output_file.path, "r") as fh: qpt, inside = None, 0 for line in fh: if line.startswith(BEGIN): qpts.append( [float(s) for s in line[len(BEGIN):].split()]) inside, omegas = 1, [] elif line.startswith(END): break elif inside: inside += 1 if inside > 2: omegas.extend((float(s) for s in line.split())) else: raise ValueError("Cannot find %s in file %s" % (END, task.output_file.path)) phfreqs.append(omegas) # Use namedtuple to store q-point and frequencies in meV phonon = collections.namedtuple("phonon", "qpt freqs") return [ phonon(qpt=qpt, freqs=freqs_meV) for qpt, freqs_meV in zip(qpts, EnergyArray(phfreqs, "Ha").to("meV")) ]
def read_etotals(self, unit="Ha"): """ Reads the total energy from the GSR file produced by the task. Return a numpy array with the total energies in Hartree The array element is set to np.inf if an exception is raised while reading the GSR file. """ if not self.all_done: raise self.Error("Some task is still in running/submitted state") etotals = [] for task in self: # Open the GSR file and read etotal (Hartree) gsr_path = task.outdir.has_abiext("GSR") etot = np.inf if gsr_path: with ETSF_Reader(gsr_path) as r: etot = r.read_value("etotal") etotals.append(etot) return EnergyArray(etotals, "Ha").to(unit)
def test_energy(self): """ Similar to FloatWithUnitTest.test_energy. Check whether EnergyArray and FloatWithUnit have same behavior. # TODO One can merge the two tests easily: for obj in [Energy, EnergyArray]: a = obj(...) self.assert(...) """ a = EnergyArray(1.1, "eV") b = a.to("Ha") self.assertAlmostEqual(float(b), 0.0404242579378) c = EnergyArray(3.14, "J") self.assertAlmostEqual(float(c.to("eV")), 1.9598339337836966e+19) # self.assertRaises(ValueError, Energy, 1, "m") d = EnergyArray(1, "Ha") self.assertAlmostEqual(float(a + d), 28.31138386) self.assertAlmostEqual(float(a - d), -26.11138386) self.assertEqual(float(a + 1), 2.1)
def bxsf_write(file, structure, nsppol, nband, ndivs, emesh_sbk, fermie, unit="eV"): """ Write band structure data in the Xcrysden format (XSF) Args: file: file-like object. structure: :class:`Structure` object. nsppol: Number of spins. nband: Number of bands. ndivs: Number of divisions of the full k-mesh. emesh_sbk: Array [nsppol, nband, ndivs[0], ndivs[1], mpdvis[2]] with the emesh_sbk in energy unit `unit`. fermie: Fermi energy. .. note:: #. The k-points must span the reciprocal unit cell, not the Brillouin zone. #. The mesh must be closed and centered on Gamma. #. Energies are written in row-major (i.e. C) order. # Energies are in Hartree. See also http://www.xcrysden.org/doc/XSF.html """ emesh_sbk = EnergyArray(emesh_sbk, unit).to("Ha") fermie = Energy(fermie, unit).to("Ha") emesh_sbk = np.reshape(emesh_sbk, (nsppol, nband, np.product(ndivs))) close_it = False if not hasattr(file, "write"): file = open(file, mode="w") close_it = True fw = file.write # Write the header. fw('BEGIN_INFO\n') fw('# Band-XCRYSDEN-Structure-File for Visualization of Fermi Surface generated by the ABINIT package\n' ) fw('# NOTE: the first band is relative to spin-up electrons,\n') fw('# the second band to spin-down electrons (if any) and so on ...\n#\n' ) fw('# Launch as: xcrysden --bxsf\n#\n') fw(' Fermi Energy: %f\n' % fermie) fw('END_INFO\n\n') fw('BEGIN_BLOCK_BANDGRID_3D\n') fw(' band_energies\n') fw(' BEGIN_BANDGRID_3D\n') fw(str(nsppol * nband) + "\n") # Number of bands written. fw("%d %d %d\n" % tuple(ndivs)) # Number of division in the full BZ mesh. fw("0 0 0\n") # Unshifted meshes are not supported. # Reciprocal lattice vectors in Ang^{-1} gcell = structure.lattice_vectors("g") for i in range(3): fw('%f %f %f\n' % tuple(gcell[i])) # Write energies on the full mesh for all spins and bands. idx = 0 for band in range(nband): for spin in range(nsppol): idx += 1 enebz = emesh_sbk[spin, band, :] fw(" BAND: %d\n" % idx) fw("\n".join("%.18e" % v for v in enebz)) fw("\n") fw(' END_BANDGRID_3D\n') fw('END_BLOCK_BANDGRID_3D\n') file.flush() if close_it: file.close()
def read_eterms(self, unit="eV"): return AttrDict( etotals=EnergyArray(self.read_value("etotal"), "Ha").to(unit), kinetic_terms=EnergyArray(self.read_value("ekin"), "Ha").to(unit), entropies=EnergyArray(self.read_value("entropy"), "Ha").to(unit), )