def test_get_dftbp_data(self): env = {} database = Database() # src = 'test_dftbutils/scc' dst = 'test.scc' get_dftbp_data(env, database, src, dst) modeldict = database.get(dst) self.assertDictEqual(modeldict, self.ref_scc) # src = 'test_dftbutils/bs' dst = 'test.bs' get_dftbp_data(env, database, src, dst) modeldict = database.get(dst) self.assertDictEqual(modeldict, self.ref_bs)
def test_objtype_values_single_model_single_data(self): """Can we create value-type objective for a single model""" yamldata = """objectives: - band_gap: doc: Band gap, Si models: Si/bs ref: 1.12 weight: 3.0 """ dat = 1.2 ow = 1. spec = yaml.load(yamldata)['objectives'][0] que = 'band_gap' ref = 1.12 www = 3.0 mnm = 'Si/bs' # set data base database = Database() database.update('Si/bs') modeldb = database.get('Si/bs') # check declaration objv = oo.get_objective(spec) self.assertEqual(objv.objtype, 'values') self.assertEqual(objv.model_names, mnm) self.assertEqual(objv.model_weights, ow) self.assertEqual(objv.weight, www) self.assertEqual(objv.ref_data, ref) self.assertEqual(objv.subweights, ow) self.assertEqual(objv.query_key, que) # check __call__() modeldb['band_gap'] = dat mdat, rdat, weights = objv.get(database) self.assertEqual(mdat, dat) self.assertEqual(rdat, ref) self.assertEqual(weights, ow)
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_evaluate_bands(self): """Can we evaluate value-type objective of type bands (2D array)""" yamldata = """objectives: - bands: models: A ref: file: ./reference_data/fakebands.dat loader_args: {unpack: False} process: rm_columns: 1 eval: [RMS, relerr] """ # set model data database = Database() database.update('A') db1 = database.get('A') # declaration of objective spec = yaml.load(yamldata)['objectives'][0] objv = oo.get_objective(spec) self.assertAlmostEqual(1., np.sum(objv.subweights)) #logger.debug(objv.ref_data) #logger.debug(objv.subweights) db1['bands'] = objv.ref_data * 1.1 cost = np.sqrt(np.sum(objv.subweights*relerr(objv.ref_data, db1['bands'])**2)) #logger.debug(cost) # evaluate self.assertAlmostEqual(cost, objv(database))
def test_execution_get_dftbp(self): """Can we execute the declared get_dftbp_* tasks?""" taskdict = {} update_taskdict(taskdict, [['skpar.core.taskdict', ['get', 'sub', 'run']]]) update_taskdict( taskdict, [['skpar.dftbutils', ['get_bs', 'get_meff', 'get_Ek']]]) userinp = yaml.load(self.yamlin) tasklist = get_tasklist(userinp['tasks']) tasks = initialise_tasks(tasklist, taskdict) # database = Database() env = { 'workroot': '.', } for task in tasks: print(task) task(env, database) # 'Si.bs' should be added through the task execution db = database.get('Si.bs') self.assertAlmostEqual(db['Egap'], 1.129, places=3) self.assertAlmostEqual(db['Ef'], -3.0621, places=4) self.assertAlmostEqual(db['me_GX'], 0.935, places=3) self.assertAlmostEqual(db['mh_GK'], -1.891, places=3) self.assertAlmostEqual(db['Ec_L_0'], 0.4, places=3) self.assertAlmostEqual(db['Ec_G_0'], 1.6156, places=3) self.assertAlmostEqual(db['Ec_X_0'], 0.2025, places=3) self.assertAlmostEqual(db['Ec_U_0'], 0.6915, places=3) self.assertAlmostEqual(db['Ec_K_0'], 0.6915, places=3)
def test_evaluate_multiplemodels_singleitem(self): """Can we evaluate value-type objective for multiple models""" yamldata = """objectives: - item: models: [A, B, C] ref: [2.0, 2., 3.] options: # normalise: True subweights: [2, 1, 1.5] """ # set model data database = Database() db1 = {'item': 1.0} db2 = {'item': 1.0} db3 = {'item': 1.0} database.update('A', db1) _db = database.get('A') self.assertDictEqual(_db, db1) database.update('B', db2) database.update('C', db3) # declaration of objective spec = yaml.load(yamldata)['objectives'][0] objv = oo.get_objective(spec) # evaluate self.assertAlmostEqual(1.4142135623730951, objv(database))
def test_simple(self): """Can we parse task declarations successfully""" jsondata = """ { "tasks": [ {"sub": [["./tmp/template.parameters.dat"]]} , {"run": ["cp parameters.dat value.dat", "./tmp"]} , {"get": ["value", "tmp/value.dat", "model"]} ] } """ yamldata = """ tasks: - sub: [[./tmp/template.parameters.dat]] - run: ["cp parameters.dat value.dat", ./tmp] - get: [value, tmp/value.dat, model] """ taskdict = {} update_taskdict(taskdict, [['skpar.core.taskdict', ['get', 'sub', 'run']]]) yamldata = yaml.load(yamldata) # print('yaml data') # pprint(yamldata) jsondata = json.loads(jsondata) # print('json data') # pprint(jsondata) # self.assertTrue(jsondata == yamldata) # fails for whatever reason tasklist = [] userinp = yamldata tasklist = get_tasklist(userinp['tasks']) tasks = initialise_tasks(tasklist, taskdict) # var = 10 database = Database() par = Parameter('p0', value=var) workroot = './' coreargs = { 'workroot': workroot, 'parametervalues': [par.value], 'parameternames': [par.name] } try: shutil.rmtree('./tmp') except FileNotFoundError: pass os.makedirs('./tmp') with open('./tmp/template.parameters.dat', 'w') as template: template.writelines("%(p0)f\n") # with open('./tmp/template.parameters.dat', 'r') as template: # tmplstr = template.readlines() # print(tmplstr) LOGGER.info('Executing tasks') for task in tasks: # LOGGER.info(task) task(coreargs, database) self.assertEqual(np.atleast_1d(var), database.get('model', {}).get('value')) shutil.rmtree('./tmp')
def test_objtype_values_single_model_array_data(self): """Can we create 1d-array-values-type objective for a single model""" yamldata = """objectives: - Etot(Vol): doc: 'Energy-Volume dependnce of Wurtziteac structure' models: GaN-W-ac ref: [-20.236, -21.099, -21.829, -22.45, -22.967, -23.387, -23.719, -23.974, -24.158, -24.278, -24.304, -24.348, -24.309, -24.228, -24.11 , -23.952, -23.769, -23.559, -23.328, -23.076, -22.809] options: subweights: [1,1,1,1,1, 2,2,2, 3,3,3,3,3, 2,2,2, 1,1,1,1,1] """ data = [-20.24,-21.1,-21.83,-22.45,-22.97, -23.4,-23.72,-23.97, -24.2,-24.3,-24.3,-24.35,-24.31, -24.23,-24.11,-23.9, -23.77,-23.56,-23.3,-23.1,-22.8] logger.info(data) que = 'Etot(Vol)' ref = [-20.236, -21.099, -21.829, -22.45,-22.967, -23.387, -23.719, -23.974, -24.158, -24.278, -24.304, -24.348, -24.309, -24.228, -24.11, -23.952, -23.769, -23.559, -23.328, -23.076, -22.809] sbw = [1,1,1,1,1, 2,2,2, 3,3,3,3,3, 2,2,2, 1,1,1,1,1] sbw = np.asarray(sbw)/np.sum(sbw) # normalise model = 'GaN-W-ac' # set data base database = Database() database.update(model) modeldb = database.get(model) # check declaration spec = yaml.load(yamldata)['objectives'][0] logger.info(spec) objv = oo.get_objective(spec) self.assertEqual(objv.model_names, model) self.assertEqual(objv.model_weights, 1.) self.assertEqual(objv.weight, 1) nptest.assert_array_equal(objv.ref_data, ref, verbose=True) nptest.assert_array_equal(objv.subweights, sbw, verbose=True) self.assertEqual(objv.query_key, que) self.assertEqual(objv.objtype, 'values') # check __call__() modeldb[que] = data mdata, rdata, weights = objv.get(database) nptest.assert_array_equal(mdata, data, verbose=True) nptest.assert_array_equal(rdata, ref, verbose=True) nptest.assert_array_equal(weights, sbw, verbose=True)
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_evaluate_singleitem(self): """Can we evaluate value-type objective for a single model""" yamldata = """objectives: - item: models: A ref: 1.0 """ # set data base database = Database() database.update('A') db = database.get('A') # declaration of objective spec = yaml.load(yamldata)['objectives'][0] objv = oo.get_objective(spec) # evaluate db['item'] = 1.2 self.assertAlmostEqual(0.2, objv(database))
def test_database(self): """Can we update model DB""" database = Database() self.assertTrue(database is not None) # database.update('m1', {'i1': 42}) self.assertDictEqual(database.all(), {'m1': {'i1': 42}}) # database.update('m1', {'i1': 33}) self.assertDictEqual(database.all(), {'m1': {'i1': 33}}) # database.update('m2', {'i1': 10}) self.assertDictEqual(database.all(), {'m1': {'i1': 33}, 'm2': {'i1': 10}}) # database.update('m2', {'i2': 20}) self.assertDictEqual(database.all(), {'m1': {'i1': 33}, 'm2': {'i1': 10, 'i2': 20}}) update(database, 'm1', {'i2': 25}) self.assertDictEqual(database.all(), {'m1': {'i1': 33, 'i2': 25}, 'm2': {'i1': 10, 'i2': 20}}) database.update({'m2': {'i3': 40}}) self.assertDictEqual(database.all(), {'m1': {'i1': 33, 'i2': 25}, 'm2': {'i3': 40}}) # mdb = database.get('m2') self.assertDictEqual(mdb, {'i3': 40}) self.assertEqual(database.get_item('m1', 'i2'), 25) # # check query initialised without database query = Query('m2', 'i1') self.assertEqual(query(database, atleast_1d=False), None) query = Query('m2', 'i3') self.assertEqual(query(database, atleast_1d=False), 40) # # check query initialised with database within database.query method self.assertEqual(database.query('m1', 'i1', atleast_1d=False), 33) nptest.assert_array_equal(database.query('m1', 'i1'), [33]) # database.clear() self.assertDictEqual(database.all(), {})
def test_twopartemplates(self): """Can we parse task declarations successfully""" yamldata = """ tasks: - sub: [[./tmp/template.par1.dat, ./tmp/template.par2.dat]] - run: ['bash run.sh', ./tmp] - get: [value, tmp/values.dat, model] """ taskdict = {} update_taskdict(taskdict, [['skpar.core.taskdict', ['get', 'sub', 'run']]]) yamldata = yaml.load(yamldata)['tasks'] tasklist = [] tasklist = get_tasklist(yamldata) tasks = initialise_tasks(tasklist, taskdict) # var1 = 10 var2 = 20 database = Database() params = [Parameter('p0', value=var1), Parameter('p1', value=var2)] workroot = './' coreargs = { 'parametervalues': [p.value for p in params], 'parameternames': [p.name for p in params] } try: shutil.rmtree('./tmp') except FileNotFoundError: pass os.makedirs('./tmp') with open('./tmp/template.par1.dat', 'w') as template: template.writelines("%(p0)f\n") with open('./tmp/template.par2.dat', 'w') as template: template.writelines("%(p1)f\n") with open('./tmp/run.sh', 'w') as template: template.writelines('cat par*.dat > values.dat\n') for task in tasks: LOGGER.info(task) task(coreargs, database) self.assertListEqual([var1, var2], list(database.get('model', {}).get('value'))) shutil.rmtree('./tmp')
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 test_parse_input(self): """Can we parse input, create an optimiser instance, and run the tasks? """ filename = "skpar_in_optimise.yaml" taskdict, tasklist, objectives, optimisation, config =\ parse_input(filename) print (taskdict) print (tasklist) workroot = config.get('workroot', None) templatedir = config.get('templatedir', None) create_workdir(workroot, templatedir) algo, options, parameters = optimisation parnames = [p.name for p in parameters] evaluate = Evaluator(objectives, tasklist, taskdict, parnames, config) optimiser = Optimiser(algo, parameters, evaluate, options) # initialise parameter values, pretending to be optimisation engine params = np.array([10.0, -2.5, 0.5, 0.05]) for pini, par in zip(params, optimiser.parameters): par.value = pini logger.debug ("### ---------------------------------------- ###") logger.debug ("### ----------- Parameters ----------------- ###") logger.debug ("### ---------------------------------------- ###") for pp in optimiser.parameters: logger.debug (pp) # initialise tasks manually optimiser.evaluate.tasks = initialise_tasks(tasklist, taskdict, report=True) env = {'workroot': workroot, 'parameternames': parnames, 'parametervalues': params, 'iteration': None} workdir = workroot database = Database() # check task 0 self.assertEqual(optimiser.evaluate.tasks[0].name, 'set') self.assertEqual(optimiser.evaluate.tasks[0].func, core_taskdict.substitute_parameters) self.assertEqual(optimiser.evaluate.tasks[0].args, [['template.parameters.dat']]) optimiser.evaluate.tasks[0](env, database) parfile = os.path.abspath(os.path.join(workdir, 'parameters.dat')) raw = np.loadtxt(parfile, dtype=[('keys', 'S15'), ('values', 'float')]) _values = np.array([pair[1] for pair in raw]) _names = [pair[0].decode("utf-8") for pair in raw] nptest.assert_array_equal(params, _values) self.assertListEqual(parnames, _names) # check task 1 exe = 'python3'.split() self.assertEqual(optimiser.evaluate.tasks[1].name, 'run') self.assertEqual(optimiser.evaluate.tasks[1].func, core_taskdict.execute) self.assertEqual(optimiser.evaluate.tasks[1].args, ['python3 model_poly3.py']) optimiser.evaluate.tasks[1](env, database) # check task 2 self.assertEqual(optimiser.evaluate.tasks[2].name, 'get') self.assertEqual(optimiser.evaluate.tasks[2].func, core_taskdict.get_model_data) self.assertEqual(optimiser.evaluate.tasks[2].args, ['yval', 'model_poly3_out.dat', 'poly3']) optimiser.evaluate.tasks[2](env, database) modeldb = database.get('poly3') self.assertTrue(modeldb is not None) datafile = os.path.abspath(os.path.join(workdir, 'model_poly3_out.dat')) dataout = np.loadtxt(datafile) nptest.assert_array_equal(modeldb['yval'], dataout) logger.debug("Model DB poly3:") logger.debug(database.get('poly3').items())
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)