def test_skparplot(self): """Can we plot a band-structure objectives?""" env = {} database = Database() latticeinfo = {'type': 'FCC', 'param': 5.4315} model = 'Si.bs' filename = '_workdir/test_plot/bs1.pdf' get_bandstructure(env, database, 'test_dftbutils/Si/bs/', model, latticeinfo=latticeinfo) modeldb = database.get(model) bands = modeldb['bands'] eps = 0.25 jitter = eps * (0.5 - random(bands.shape)) altbands = bands + jitter if os.path.exists(filename): os.remove(filename) else: os.makedirs('_workdir/test_plot', exist_ok=True) skparplot(modeldb['kvector'], [altbands, bands], filename=filename, xticklabels=modeldb['kticklabels'], xlabel='wave-vector', ylabel='Energy, eV', linelabels=['ref', 'model'], ylim=(-13, 6)) self.assertTrue(os.path.exists(filename))
def test_get_special_Ek_options(self): """Get E(k) for explicitly given, and multiple bands""" env = {} database = Database() model = 'test.Ek' src = 'test_dftbutils/Si/bs' get_bandstructure(env, database, src, model, latticeinfo={ 'type': 'FCC', 'param': 5.431 }) dst = database.get(model) get_special_Ek(env, database, model, model, sympts=['K', 'L'], extract={ 'cb': [0, 2, 4, 6], 'vb': [0, 2, 4, 6] }) self.assertAlmostEqual(dst['Ec_L_4'], 2.8089, places=3) self.assertAlmostEqual(dst['Ec_L_0'], 0.3995, places=3) self.assertAlmostEqual(dst['Ec_K_0'], 0.6915, places=3) # self.assertAlmostEqual(dst['Ev_L_0'], -2.5016, places=3) self.assertAlmostEqual(dst['Ev_L_4'], -7.842, places=3) self.assertAlmostEqual(dst['Ev_L_6'], -11.3369, places=3) self.assertAlmostEqual(dst['Ev_K_0'], -3.5884, places=3) self.assertAlmostEqual(dst['Ev_K_2'], -4.963, places=3) self.assertAlmostEqual(dst['Ev_K_4'], -8.694, places=3) self.assertAlmostEqual(dst['Ev_K_6'], -9.8759, places=3)
def test_get_special_Ek(self): """Get E(k) for k obtained from the kLines""" env = {} database = Database() model = 'test.Ek' src = 'test_dftbutils/Si/bs' get_bandstructure(env, database, src, model, latticeinfo={ 'type': 'FCC', 'param': 5.431 }) dst = database.get(model) get_special_Ek(env, database, model, model) self.assertAlmostEqual(dst['Ec_L_0'], 0.4, places=3) self.assertAlmostEqual(dst['Ec_G_0'], 1.616, places=3) self.assertAlmostEqual(dst['Ec_X_0'], 0.2025, places=3) self.assertAlmostEqual(dst['Ec_U_0'], 0.6915, places=3) self.assertAlmostEqual(dst['Ec_K_0'], 0.6915, places=3) # self.assertAlmostEqual(dst['Ev_L_0'], -2.5016, places=3) self.assertAlmostEqual(dst['Ev_G_0'], -1.1289, places=3) self.assertAlmostEqual(dst['Ev_X_0'], -3.9592, places=3) self.assertAlmostEqual(dst['Ev_U_0'], -3.5885, places=3) self.assertAlmostEqual(dst['Ev_K_0'], -3.5885, places=3)
def test_get_bandstructure(self): """Can we get the bandstructure and gap/cb/vb details?""" env = {} database = Database() src = 'test_dftbutils/bs' dst = 'test.bs' get_bandstructure(env, database, src, dst) modeldict = database.get(dst) nptest.assert_array_almost_equal(modeldict['bands'], self.ref_bands) self.assertEqual(modeldict['nkpts'], self.ref_nk) self.assertEqual(modeldict['nbands'], self.ref_nb) self.assertEqual(modeldict['Ef'], self.ref_Ef) self.assertEqual(modeldict['Egap'], self.ref_Eg) self.assertEqual(modeldict['Ecb'], self.ref_Ec) self.assertEqual(modeldict['Evb'], self.ref_Ev)
def test_get_kvec_abscissa2(self): """Can we get the bandstructure and extract the kvector info""" latticeinfo = {'type': 'FCC', 'param': 1.} lat = Lattice(latticeinfo) database = Database() src = 'test_dftbutils/bs' get_bandstructure({'workroot': '.'}, database, src, 'test', latticeinfo=latticeinfo) kLines = database.get_item('test', 'kLines') bands = database.get_item('test', 'bands') logger.debug('Bands.shape: {}'.format(bands.shape)) logger.debug('kLines : {}'.format(kLines)) xx, xt, xl = get_kvec_abscissa(lat, kLines) refxl = ['X', 'Γ', 'K', 'L', 'Γ'] refxt = [0, 6.28319, 12.94751, 16.79516, 22.23656] self.assertListEqual(xl, refxl) nptest.assert_almost_equal(xt, refxt, 5) self.assertAlmostEqual(xx[-1], xt[-1]) self.assertEqual(len(xx), kLines[-1][-1]+1)
def test_get_effmasses_default(self): """Can we get effective masses in addition to band-structure, with default settings?""" env = {} database = Database() src = 'test_dftbutils/Si/bs' model = 'test.meff' get_bandstructure(env, database, src, model, latticeinfo={ 'type': 'FCC', 'param': 5.431 }) dst = database.get(model) # the values below are in oldskpar.debug.log in the above dir self.assertTrue(dst['withSOC']) self.assertEqual(dst['ivbtop'], 7) self.assertEqual(dst['nkpts'], 206) self.assertEqual(dst['nbands'], 36) self.assertAlmostEqual(dst['Ef'], -3.0621, places=3) self.assertAlmostEqual(dst['Egap'], 1.1289, places=3) self.assertAlmostEqual(dst['Ecb'], -3.06221, places=3) self.assertAlmostEqual(dst['Evb'], -4.19099, places=3) # ref_klines = [('L', 0), ('Gamma', 53), ('X', 113), ('U', 141), ('K', 142), ('Gamma', 205)] ref_klinesdict = { 'K': [142], 'X': [113], 'Gamma': [53, 205], 'L': [0], 'U': [141] } self.assertListEqual(dst['kLines'], ref_klines) self.assertDictEqual(dst['kLinesDict'], ref_klinesdict) get_effmasses(env, database, model, model) ref_meff_tags = ['me_LG', 'me_GX', 'me_XU', 'me_KG'] ref_meff_tags.extend(['mh_LG', 'mh_GX', 'mh_XU', 'mh_KG']) self.assertTrue(all([key in dst for key in ref_meff_tags]))
def main_bands(args): """ Chain the relevant tasks for obtaining band-structure and execute. """ # setup logger # ------------------------------------------------------------------- loglevel = logging.DEBUG if args.verbose else logging.INFO logger = get_logger(name='dftbutils', filename='dftbutils.bands.log', verbosity=loglevel) #logger.info(args) # deal with bands-specific arguments if any # -------------------------------------------------- workroot = '.' workdir = abspath(expanduser(args.workdir)) sccdir = abspath(joinpath(workdir, 'scc')) sccchg = abspath(joinpath(sccdir, 'charges.bin')) bsdir = abspath(joinpath(workdir, 'bs')) dftb = args.dftb dftblog = 'dftb.log' bands = args.bands if args.dos: dos = args.dos bandslog = 'dp_bands.log' if not args.plot_only: # Execute the necessary commands # scc calculation execute(cmd=dftb, workdir=sccdir, outfile=dftblog) # check log execute(cmd=['check_dftblog', dftblog], workdir=sccdir, outfile='chk.log') # extract dos for plotting if args.dos: execute(cmd=[dos, 'band.out', 'dos_total.dat'], workdir=sccdir, outfile=bandslog) # copy charges for klines calculation execute(cmd=['cp', '-f', sccchg, bsdir], workdir='.', outfile=None) # klines calculation execute(cmd=dftb, workdir=bsdir, outfile=dftblog) # check log execute(cmd=['check_dftblog', dftblog], workdir=sccdir, outfile='chk.log') # extract bands for plotting execute(cmd=[bands, 'band.out', 'bands'], workdir=bsdir, outfile=bandslog) if args.plot or args.plot_only: # hack the plotting directly, not via tasks, to avoid needing objectives database = {} implargs = {'workroot': workroot} get_bandstructure(implargs, database, bsdir, 'dftb', latticeinfo=args.latticeinfo) bsdata = database.get('dftb') logger.info('Band-gap (eV) = {:.3f}'.format(bsdata['Egap'])) yy1 = bsdata['bands'] - bsdata['Evb'] if args.latticeinfo: xx1 = bsdata['kvector'] xtl = bsdata['kticklabels'] else: xx1 = np.asarray(range(yy1.shape[1])) xtl = None filename = os.path.join(workroot, workdir, 'bs.pdf') plot_bs(xx1, yy1, filename=filename, ylim=args.ylim, xticklabels=xtl)
def test_get_effmasses_select(self): """Can we get select effective masses with a control options?""" env = {} database = Database() model = 'test.meff' # NOTABENE: the refdata here is from SOC calculation!!! src = 'test_dftbutils/Si/bs' get_bandstructure(env, database, src, model, latticeinfo={ 'type': 'FCC', 'param': 5.431 }) dst = database.get(model) directions = ['Gamma-X', 'Gamma-L', 'Gamma-K'] # Example how to extract different masses over a different energy window: # Note that subsequent extractions overwrite final data in dst, so we start with # the deepest bands, and than reduce the number of bands, towards to top of VB # The energy window should be adjusted depending on the anticipated curvature of the band get_effmasses(env, database, model, model, directions=directions, carriers='e', nb=1, Erange=0.005, usebandindex=True) # get the lowest band masses: (spin-orbit); forceErange seems to not work properly? get_effmasses(env, database, model, model, directions=directions, carriers='h', nb=5, Erange=0.0015, forceErange=True) # get the light hole bands (3 and 4) get_effmasses(env, database, model, model, directions=directions, carriers='h', nb=3, Erange=0.008) # get the top two (heavy hole) bands (1 and 2); enforce indexing! (i.e. add _0) get_effmasses(env, database, model, model, directions=directions, carriers='h', nb=1, Erange=0.002, usebandindex=True) self.assertAlmostEqual(dst['me_GX_0'], 0.935, places=3) self.assertAlmostEqual(dst['mh_GX_0'], -0.278, places=2) self.assertAlmostEqual(dst['mh_GK_0'], -1.891, places=3) self.assertAlmostEqual(dst['mh_GL_0'], -0.633, places=3) self.assertAlmostEqual(dst['mh_GX_2'], -0.286, places=3) self.assertAlmostEqual(dst['mh_GK_2'], -0.362, places=3) self.assertAlmostEqual(dst['mh_GL_2'], -2.2426, places=3) self.assertAlmostEqual(dst['mh_GX_4'], -0.1389, places=3) self.assertAlmostEqual(dst['mh_GK_4'], -0.095, places=3) self.assertAlmostEqual(dst['mh_GL_4'], -0.086, places=3) self.assertAlmostEqual(dst['cbminpos_GX_0'], 0.817, places=2)