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_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_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_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_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_objtype_keyvaluepairs(self): """Can we create objective from given key-value pairs""" yamldata = """objectives: - meff: doc: Effective masses, Si models: Si/bs ref: file: ./reference_data/meff-Si.dat loader_args: dtype: # NOTABENE: yaml cannot read in tuples, so we must # use the dictionary formulation of dtype names: ['keys', 'values'] formats: ['S15', 'float'] options: normalise: false subweights: # consider only a couple of entries from available data dflt: 0. me_GX_0: 2. mh_GX_0: 1. weight: 1.5 """ spec = yaml.load(yamldata)['objectives'][0] que = 'meff' # NOTABENE: order here must coincide with order in ref:file ref = np.array([('me_GX_0', 0.916), ('mh_GX_0', -0.276)], dtype=[('keys', 'S15'), ('values', 'float')]) ref = ref['values'] subw = np.array([2., 1.]) doc = spec[que]['doc'] oww = spec[que]['weight'] mnm = spec[que]['models'] # check declaration objv = oo.get_objective(spec) logger.debug(objv) self.assertEqual(objv.doc, doc) self.assertEqual(objv.weight, oww) self.assertEqual(objv.model_names, mnm) self.assertEqual(objv.model_weights, 1.) nptest.assert_array_equal(objv.ref_data, ref, verbose=True) nptest.assert_array_equal(objv.subweights, subw, verbose=True) self.assertEqual(objv.query_key, ['me_GX_0', 'mh_GX_0']) self.assertEqual(objv.objtype, 'keyval_pairs') # set data base: # could be done either before or after declaration database = Database() dat = [0.9, -0.5, 1.2] database.update('Si/bs', {'me_GX_0': dat[0], 'mh_GX_0': dat[1], 'me_GL_2':dat[2]}) # check __call__() mdat, rdat, weights = objv.get(database) #logger.debug(mdat) #logger.debug(rdat) #logger.debug(weights) # NOTABENE: order depends on the order in the reference file!!! nptest.assert_array_equal(mdat, np.asarray(dat[0:2]), verbose=True) nptest.assert_array_equal(rdat, ref, verbose=True) nptest.assert_array_equal(weights, subw, verbose=True)
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_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_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_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_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_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_objtype_weightedsum(self): """Can we create objective from pairs of value-weight""" yamldata = """objectives: - Etot: doc: "heat of formation, SiO2" models: - [SiO2-quartz/scc, 1.] - [Si/scc, -0.5] - [O2/scc, -1] ref: 1.8 weight: 1.2 """ spec = yaml.load(yamldata)['objectives'][0] que = 'Etot' ref = spec[que]['ref'] doc = spec[que]['doc'] oww = spec[que]['weight'] mnm = [m[0] for m in spec[que]['models']] mww = np.asarray([m[1] for m in spec[que]['models']]) subw = 1. # set data base: # could be done either before or after declaration database = Database() # check declaration objv = oo.get_objective(spec) self.assertEqual(objv.doc, doc) self.assertEqual(objv.weight, oww) self.assertEqual(objv.model_names, mnm) nptest.assert_array_equal(objv.model_weights, mww, verbose=True) self.assertEqual(objv.ref_data, ref) self.assertEqual(objv.subweights, subw) self.assertEqual(objv.query_key, 'Etot') self.assertEqual(objv.objtype, 'weighted_sum') dat = [20, 12, 16] database.update('SiO2-quartz/scc', {'Etot': dat[0]}) database.update('Si/scc', {'Etot': dat[1]}) database.update('O2/scc', {'Etot': dat[2]}) # check __call__() mdat, rdat, weights = objv.get(database) nptest.assert_array_equal(mdat, np.dot(np.asarray(dat), np.asarray(mww)), verbose=True) nptest.assert_array_equal(rdat, ref, verbose=True) nptest.assert_array_equal(weights, subw, verbose=True)
def evaluate(self, parametervalues, iteration=None): """Evaluate the global fitness of a given point in parameter space. This is the only object accessible to the optimiser, therefore only two arguments can be passed. Args: parametervalues (list): current point in design/parameter space iteration: (int or tupple): current iteration or current generation and individual index within generation Return: fitness (float): global fitness of the current design point """ # Create individual working directory for each evaluation origdir = os.getcwd() workroot = self.config['workroot'] if workroot is None: workdir = origdir else: workdir = get_workdir(iteration, workroot) create_workdir(workdir, self.config['templatedir']) # Initialise model database self.logger.info('Initialising ModelDataBase.') # database may be something different than a dictionary, but # whatever object it is, should have: # update_modeldb(modelname, datadict) -- update modeldb # get_modeldb(modelname) -- return a ref to modeldb # The point is that for every individual evaluation, we must # have individual model DB, so evaluations can be done in parallel. database = Database() # database = {} currently works too # Wrap the environment in a single dict env = { 'workroot': workdir, 'logger': self.logger, 'parameternames': self.parnames, 'parametervalues': parametervalues, 'iteration': iteration, 'taskdict': self.taskdict, 'objectives': self.objectives } # Initialise and then execute the tasks tasks = initialise_tasks(self.tasklist, self.taskdict, report=False) self.logger.info('Iteration %s', iteration) self.logger.info('===========================') if self.parnames: parstr = [ '{:s}({:.4g})'.format(name, val) for name, val in zip(self.parnames, parametervalues) ] self.logger.info('Parameters: {:s}'.format(' '.join(parstr))) # do we really need to pass workdir and to os.chdir??? # move the for loop to a function. # execute_tasks(tasks, env, database, workdir, logger) for i, task in enumerate(tasks): os.chdir(workdir) try: task(env, database) except: self.logger.critical('Task %i FAILED:\n%s', i, task) raise # Evaluate individual fitness for each objective objvfitness = eval_objectives(self.objectives, database) # Evaluate global fitness cost = self.costf(self.utopia, objvfitness, self.weights) self._msg('{:<15s}: {}\n'.format('Overall cost', cost)) # Remove iteration-specific working dir if not needed: if (not self.config['keepworkdirs']) and (workroot is not None): destroy_workdir(workdir) os.chdir(origdir) return np.atleast_1d(cost)
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_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_objtype_bands(self): """Can we create objective from spec for bands?""" yamldata = """objectives: - bands: doc: Valence Band, Si models: Si/bs ref: file: ./reference_data/fakebands.dat loader_args: {unpack: True} process: # eliminate unused columns, like k-pt enumeration # indexes and ranges below refer to file, not array, # i.e. independent of 'unpack' loader argument rm_columns: 1 # filter k-point enumeration, and bands, potentially # rm_rows : [[18,36], [1,4]] # filter k-points if needed for some reason # scale : 1 # for unit conversion, e.g. Hartree to eV, if needed options: use_ref: [[2, 4]] # fortran-style index-bounds of bands to use use_model: [[1, 3]] # model has lesser number of bands # Alignment works after data has been masked by use_* clause, and therefore # the indexes below do not correspond to original but masked array align_ref: [3, max] # fortran-style index of band and k-point, align_model: [3, max] # or a function (e.g. min, max) instead of k-point normalise: false subweights: # NOTABENE: # -------------------------------------------------- # Energy values are with respect to the ALIGNEMENT. # If we want to have the reference band index as zero, # we would have to do tricks with the range specification # behind the curtain, to allow both positive and negative # band indexes, e.g. [-3, 0], INCLUSIVE of either boundary. # Currently this is not done, so only standard Fortran # range spec is supported. Therefore, band 1 is always # the lowest lying, and e.g. band 4 is the third above it. # -------------------------------------------------- dflt: 1 values: # [[range], subweight] for E-k points in the given range of energy # notabene: the range below is with respect to the alignment value - [[-0.2, 0.], 3.5] bands: # [[range], subweight] of bands indexes; fortran-style - [[2, 3], 1.5] # two valence bands below the top VB - [4 , 3.0] # emphasize the reference band # not supported yet ipoint: weight: 1.0 """ spec = yaml.load(yamldata)['objectives'][0] que = 'bands' doc = spec[que]['doc'] model = 'Si/bs' mww = [1] oww = 1 ref = np.loadtxt('reference_data/fakebands.dat', unpack=True) ref = ref[2:5] # remove 1st col of file(k-pt enum.), consider first 3 bands from 2nd shift = -0.4 # this is the top of the VB (cf: fakebands.dat) ref -= shift shape = ref.shape # we have use_model => only a subset of bands is needed subset_ind = np.array([0,1,2]) # subweights subw = np.ones(shape) subw[1:2] = 1.5 subw[2] = 3.0 # subweights on value are the last one to be applied subw[ref > -0.2] = 3.5 subw = subw/np.sum(subw) database = Database() # # check declaration objv = oo.get_objective(spec) self.assertEqual(objv.doc, doc) self.assertEqual(objv.query_key, que) self.assertEqual(objv.weight, oww) self.assertEqual(objv.model_names, model) nptest.assert_array_equal(objv.model_weights, mww) nptest.assert_array_equal(objv.ref_data, ref, verbose=True) nptest.assert_array_equal(objv.subset_ind, subset_ind, verbose=True) nptest.assert_array_equal(objv.subweights, subw, verbose=True) # check the __call__() data = np.loadtxt("reference_data/fakebands-2.dat", unpack=True) database.update('Si/bs', {'bands': data[1:]}) mdat, rdat, weights = objv.get(database) nptest.assert_array_almost_equal(mdat, ref, decimal=2, verbose=True) nptest.assert_array_equal(rdat, ref, verbose=True) nptest.assert_array_equal(weights, subw, verbose=True)
def test_objtype_values_multiple_models(self): """Can we create a value-type objective from several models""" yamldata = """objectives: - Etot: doc: Energy vs volume, Si models: [Si/scc-1, Si/scc, Si/scc+1,] ref: [23., 10, 15.] options: normalise: false subweights: [1., 3., 1.,] """ spec = yaml.load(yamldata)['objectives'][0] que = 'Etot' ref = [23., 10, 15.] mnm = ['Si/scc-1', 'Si/scc', 'Si/scc+1',] subw = [1., 3., 1.] # check declaration objv = oo.get_objective(spec) self.assertEqual(objv.model_names, mnm) self.assertEqual(objv.weight, 1) nptest.assert_array_equal(objv.model_weights, [1]*3, verbose=True) nptest.assert_array_equal(objv.ref_data, ref, verbose=True) nptest.assert_array_equal(objv.subweights, subw, verbose=True) self.assertEqual(objv.query_key, que) # set data base: # could be done either before or after declaration database = Database() database.update('Si/scc-1') database.update('Si/scc') database.update('Si/scc+1') dat = [20, 12, 16] database.update('Si/scc-1', {'Etot': dat[0]}) database.update('Si/scc', {'Etot': dat[1]}) database.update('Si/scc+1', {'Etot': dat[2]}) # check __call__() mdat, rdat, weights = objv.get(database) nptest.assert_array_equal(mdat, dat, verbose=True) nptest.assert_array_equal(rdat, ref, verbose=True) nptest.assert_array_equal(weights, subw, verbose=True)
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)