def find_gs_structure(ceBulk, mg_conc): fname = "data/{}.json".format(db_name.split(".")[0]) with open(fname, 'r') as infile: ecis = json.load(infile) calc = CE(ceBulk, ecis) ceBulk.atoms.set_calculator(calc) conc = {"Mg": mg_conc, "Al": 1.0 - mg_conc} calc.set_composition(conc) print(ceBulk.basis_functions) formula = ceBulk.atoms.get_chemical_formula() temps = [ 800, 700, 500, 300, 200, 100, 50, 20, 19, 18, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ] n_steps_per = 1000 lowest_struct = mcobs.LowestEnergyStructure(calc, None) for T in temps: print("Temperature {}".format(T)) mc_obj = mc.Montecarlo(ceBulk.atoms, T) lowest_struct.mc_obj = mc_obj mc_obj.attach(lowest_struct) mc_obj.runMC(steps=n_steps_per, verbose=False) thermo = mc_obj.get_thermodynamic() print("Mean energy: {}".format(thermo["energy"])) fname = "data/gs_structure%s.xyz" % (formula) write(fname, lowest_struct.lowest_energy_atoms) print("Lowest energy found: {}".format(lowest_struct.lowest_energy)) print("GS structure saved to %s" % (fname)) fname = "data/cf_functions_gs%s.csv" % (formula) cf = calc.get_cf() with open(fname, 'w') as outfile: for key, value in cf.iteritems(): outfile.write("{},{}\n".format(key, value)) print("CFs saved to %s" % (fname)) return lowest_struct.lowest_energy
def test_chemical_potential(self): if not available: self.skipTest(avail_msg) bc = get_ternary_BC() ecis = {"c1_0": 0.0, "c1_1": 0.0} atoms = bc.atoms.copy() bf = bc.basis_functions calc = CE(atoms, bc, eci=ecis) groups = [{"Al": 2}, {"Mg": 1, "Si": 1}] symbs = ["Al", "Mg", "Si"] T = 400 chem_pots = [-0.2, -0.1, 0.0, 0.1, 0.2, 1.0] all_al = ["Al" for _ in range(len(atoms))] num_atom_per_fu = 2 for mu in chem_pots: calc.set_symbols(all_al) mc = PseudoBinarySGC(atoms, T, chem_pot=mu, symbols=symbs, groups=groups) # At this point the chemical potentials should # be updated changes = [(0, "Al", "Mg"), (1, "Al", "Si")] energy = calc.get_energy() for change in changes: calc.update_cf(change) new_energy = calc.get_energy() self.assertAlmostEqual(new_energy - energy, mu) mc.reset_ecis()
def __init__(self, BC): self.bc = BC cf_obj = CorrFunction(self.bc) self.init_cf = cf_obj.get_cf(self.bc.atoms) ecis = {key: 1.0 for key in self.init_cf.keys()} # ECIs do not matter here self.calc = CE(self.bc, ecis, initial_cf=self.init_cf) self.bc.atoms.set_calculator(self.calc) self.elements = self.bc.basis_elements[ 0] # This should be updated to handle different site types self.status_every_sec = 30 N = len(ecis.keys()) - 1 self.cov_matrix = np.zeros((N, N)) self.exp_value = np.zeros(N)
def test_double_swaps_ternary( self ): if ( not has_ase_with_ce ): # Disable this test self.skipTest("ASE version has not cluster expansion") return db_name = "test_db_ternary.db" conc_args = { "conc_ratio_min_1":[[4,0,0]], "conc_ratio_max_1":[[0,4,0]], "conc_ratio_min_1":[[2,2,0]], "conc_ratio_max_2":[[1,1,2]] } max_dia = get_max_cluster_dia_name() size_arg = {max_dia:4.05} ceBulk = CEBulk( crystalstructure="fcc", a=4.05, size=[4,4,4], basis_elements=[["Al","Mg","Si"]], \ conc_args=conc_args, db_name=db_name, max_cluster_size=3, **size_arg) ceBulk.reconfigure_settings() corr_func = CorrFunction( ceBulk ) cf = corr_func.get_cf( ceBulk.atoms ) #prefixes = [name.rpartition("_")[0] for name in cf.keys()] #prefixes.remove("") eci = {name:1.0 for name in cf.keys()} calc = CE( ceBulk, eci ) n_tests = 10 # Insert 25 Mg atoms and 25 Si atoms n = 18 for i in range(n): calc.calculate( ceBulk.atoms, ["energy"], [(i,"Al","Mg")]) calc.calculate( ceBulk.atoms, ["energy"], [(i+n,"Al","Si")]) updated_cf = calc.get_cf() brute_force = corr_func.get_cf_by_cluster_names( ceBulk.atoms, updated_cf.keys() ) for key in updated_cf.keys(): self.assertAlmostEqual( brute_force[key], updated_cf[key]) # Swap atoms for i in range(n_tests): indx1 = np.random.randint(low=0,high=len(ceBulk.atoms)) symb1 = ceBulk.atoms[indx1].symbol indx2 = indx1 symb2 = symb1 while( symb2 == symb1 ): indx2 = np.random.randint( low=0, high=len(ceBulk.atoms) ) symb2 = ceBulk.atoms[indx2].symbol calc.calculate( ceBulk.atoms, ["energy"], [(indx1,symb1,symb2),(indx2,symb2,symb1)]) update_cf = calc.get_cf() brute_force = corr_func.get_cf_by_cluster_names( ceBulk.atoms, update_cf.keys() ) for key,value in brute_force.items(): self.assertAlmostEqual( value, update_cf[key])
def get_gs(self, BC, ecis=None, composition=None, temps=None, n_steps_per_temp=1000, atoms=None): """ Computes the ground states :param BC: Instance of *CEBulk* or *CECrystal* from ASE :param ecis: Dictionary with the Effecitve Cluster Interactions :param composition: Dictionary with compositions (i.e. {"Mg":0.2,"Al":0.8}) :param temps: List of cooling temperatures :param n_steps_per_temp: Number of MC steps per temperature """ if atoms is None: atoms = BC.atoms.copy() if atoms.get_calculator() is None: if ecis is None: raise ValueError("When a calculator is not attached " "the ECIs has to be given!") calc = CE(atoms, BC, ecis) else: calc = atoms.get_calculator() #print (calc.get_cf()) if (temps is None): temps = np.linspace(1, 1500, 30)[::-1] if (composition is not None): calc.set_composition(composition) minimum_energy = LowestEnergyStructure(calc, None) for T in temps: print("Temperature {}".format(T)) mc_obj = Montecarlo(atoms, T) mc_obj.constraints = self.constraints minimum_energy.mc_obj = mc_obj mc_obj.attach(minimum_energy) mc_obj.runMC(steps=n_steps_per_temp, verbose=False, equil=False) thermo = mc_obj.get_thermodynamic() result = { "atoms": minimum_energy.atoms, "energy": minimum_energy.lowest_energy, "cf": minimum_energy.lowest_energy_cf } return result
def test_no_throw(self): if not available: self.skipTest(skipMsg) no_throw = True msg = "" try: bc = get_ternary_BC() eci = get_example_ecis(bc) atoms = bc.atoms.copy() CE(atoms, bc, eci=eci) mc = Montecarlo(atoms, 1000) mc.insert_symbol_random_places("Mg", num=10, swap_symbs=["Al"]) # Note: convergence_factor should never be # set to a negative value! Here it is done # to make the test converged after one step bias = AdaptiveBiasReactionPathSampler( mc_obj=mc, react_crd_init=DummyReacCrdInit(), react_crd=[-1.0, 1.0], convergence_factor=-1.0) bias.run() except Exception as exc: msg = str(exc) no_throw = False self.assertTrue(no_throw, msg=msg)
def test_with_bias_potential(self): if not available: self.skipTest(avail_msg) msg = "" try: os.remove("test_db_ternary.db") except Exception: pass no_throw = True try: bc = get_ternary_BC() ecis = get_example_ecis(bc=bc) atoms = bc.atoms.copy() calc = CE(atoms, bc, eci=ecis) groups = [{"Al": 2}, {"Mg": 1, "Si": 1}] symbs = ["Al", "Mg", "Si"] T = 400 mc = PseudoBinarySGC(atoms, T, chem_pot=-0.2, symbols=symbs, groups=groups) conc_init = PseudoBinaryConcInitializer(mc) reac_crd = np.linspace(0.0, 1.0, 10) bias_pot = reac_crd**2 bias = PseudoBinaryFreeEnergyBias(conc_init, reac_crd, bias_pot) mc.add_bias(bias) mc.runMC(mode="fixed", steps=100, equil=False) os.remove("test_db_ternary.db") except Exception as exc: msg = "{}: {}".format(type(exc).__name__, str(exc)) no_throw = False self.assertTrue(no_throw, msg)
def test_no_throw(self): if not available: self.skipTest(avail_msg) msg = "" try: os.remove("test_db_ternary.db") except Exception: pass no_throw = True try: bc = get_ternary_BC() ecis = get_example_ecis(bc=bc) atoms = bc.atoms.copy() calc = CE(atoms, bc, eci=ecis) groups = [{"Al": 2}, {"Mg": 1, "Si": 1}] symbs = ["Al", "Mg", "Si"] T = 400 mc = PseudoBinarySGC(atoms, T, chem_pot=-0.2, symbols=symbs, groups=groups) mc.runMC(mode="fixed", steps=100, equil=False) os.remove("test_db_ternary.db") except Exception as exc: msg = "{}: {}".format(type(exc).__name__, str(exc)) no_throw = False self.assertTrue(no_throw, msg)
def test_pair_observer(self): if not available: self.skipTest(skip_msg) no_throw = True msg = "" bc = get_ternary_BC() ecis = get_example_ecis(bc=bc) atoms = bc.atoms.copy() calc = CE(atoms, bc, eci=ecis) atoms.set_calculator(calc) T = 1000 nn_names = [name for name in bc.cluster_family_names if int(name[1]) == 2] mc = FixedNucleusMC( atoms, T, network_name=nn_names, network_element=["Mg", "Si"]) mc.insert_symbol_random_places("Mg", swap_symbs=["Al"]) elements = {"Mg": 3, "Si": 3} mc.grow_cluster(elements) obs = PairObserver(mc.atoms, cutoff=4.1, elements=["Mg", "Si"]) mc.attach(obs) mc.runMC(steps=200) self.assertEqual(obs.num_pairs, obs.num_pairs_brute_force()) self.assertTrue(obs.symbols_is_synced())
def test_no_throw(self): no_throw = True if not available: self.skipTest(reason) return msg = "" # try: conc_args = { "conc_ratio_min_1": [[1, 0]], "conc_ratio_max_1": [[0, 1]], } kwargs = { "crystalstructure": "fcc", "a": 4.05, "size": [4, 4, 4], "basis_elements": [["Al", "Mg"]], "conc_args": conc_args, "db_name": "data/temporary_bcnucleationdb.db", "max_cluster_size": 3 } ceBulk = CEBulk(**kwargs) ceBulk.reconfigure_settings() cf = CorrFunction(ceBulk) cf = cf.get_cf(ceBulk.atoms) ecis = {key: 1.0 for key in cf.keys()} calc = CE(ceBulk, ecis) ceBulk = calc.BC ceBulk.atoms.set_calculator(calc) T = 500 c_mg = 0.4 comp = {"Mg": c_mg, "Al": 1.0 - c_mg} calc.set_composition(comp) act_sampler = ActivitySampler(ceBulk.atoms, T, moves=[("Al", "Mg")], mpicomm=comm) act_sampler.runMC(mode="fixed", steps=1000) act_sampler.get_thermodynamic() # except Exception as exc: # msg = str(exc) # no_throw = False self.assertTrue(no_throw, msg=msg)
def get_cebulk(self): conc = Concentration(basis_elements=[["Al","Mg"]]) ceBulk = CEBulk(crystalstructure="fcc", a=4.05, size=[3,3,3], concentration=conc, db_name=db_name, max_cluster_size=3, max_cluster_dia=4.5) ceBulk.reconfigure_settings() cf = CorrFunction(ceBulk) cf = cf.get_cf(ceBulk.atoms) ecis = {key:1.0 for key in cf.keys()} atoms = ceBulk.atoms.copy() calc = CE( atoms, ceBulk, ecis ) return atoms
def __init__(self, ground_states): self.calcs = [] self.orig_symbols = [] for ground_state in ground_states: self.calcs.append( CE(ground_state["atoms"], ground_state["bc"], ground_state["eci"], initial_cf=ground_state["cf"])) symbs = [atom.symbol for atom in ground_state["atoms"]] self.orig_symbols.append(symbs)
def __init__(self, ground_states): self.calcs = [] self.orig_symbols = [] for ground_state in ground_states: self.calcs.append( CE(ground_state["bc"], ground_state["eci"], initial_cf=ground_state["cf"])) ground_state["bc"].atoms.set_calculator(self.calcs[-1]) symbs = [atom.symbol for atom in ground_state["bc"].atoms] self.orig_symbols.append(symbs)
def get_atoms(self, atomID, eci): """ Returns an instance of the atoms object requested """ db = connect(self.wl_db_name) row = db.get(id=atomID) bcfname = row.key_value_pairs["bcfile"] init_cf = row.data["cf"] try: with open(bcfname, 'rb') as infile: bc, atoms = pck.load(infile) calc = CE(atoms, bc, eci, initial_cf=init_cf) return atoms except IOError as exc: print(str(exc)) print("Will try to recover the CEBulk object") bc_kwargs = row.data["bc_kwargs"] cetype = row.key_value_pairs["cetype"] if (cetype == "CEBulk"): small_bc = CEBulk(**bc_kwargs) small_bc.reconfigure_settings() else: small_bc = CECrystal(**bc_kwargs) small_bc.reconfigure_settings() size = row.data["supercell_size"] atoms = get_atoms_with_ce_calc(small_bc, bc_kwargs, eci=eci, size=size) calc = atoms.get_calculator() # Determine the composition count = row.count_atoms() for key in count.keys(): count /= float(row.natoms) calc.set_composition(count) return atoms except: raise RuntimeError( "Did not manage to return the atoms object with the proper calculator attached..." )
def test_run(self): if not available: self.skipTest(reason) bc = get_ternary_BC() eci = get_example_ecis(bc) atoms = bc.atoms.copy() calc = CE(atoms, bc, eci=eci) mc = Montecarlo(atoms, 1000000) mc.insert_symbol_random_places("Mg", swap_symbs=["Al"], num=3) performance_monitor = MultithreadPerformance(4) performance_monitor.run(mc, 100)
def get_cebulk(self): conc_args = { "conc_ratio_min_1":[[1,0]], "conc_ratio_max_1":[[0,1]], } ceBulk = CEBulk( crystalstructure="fcc", a=4.05, size=[3,3,3], basis_elements=[["Al","Mg"]], conc_args=conc_args, db_name=db_name) ceBulk.reconfigure_settings() cf = CorrFunction(ceBulk) cf = cf.get_cf(ceBulk.atoms) ecis = {key:1.0 for key in cf.keys()} calc = CE( ceBulk, ecis ) ceBulk.atoms.set_calculator(calc) return ceBulk
def test_set_singlets( self ): if ( not has_ase_with_ce ): self.skipTest( "ASE version does not have CE" ) return system_types = [["Al","Mg"],["Al","Mg","Si"],["Al","Mg","Si","Cu"]] db_name = "test_singlets.db" n_concs = 4 no_throw = True msg = "" try: for basis_elems in system_types: conc_args = { "conc_ratio_min_1":[[1,0]], "conc_ratio_max_1":[[0,1]], } a = 4.05 mx_dia_name = get_max_cluster_dia_name() size_arg = {mx_dia_name:a} ceBulk = CEBulk( crystalstructure="fcc", a=a, size=[5, 5, 5], basis_elements=[basis_elems], conc_args=conc_args, \ db_name=db_name, max_cluster_size=2,**size_arg) ceBulk.reconfigure_settings() cf = CorrFunction(ceBulk) corrfuncs = cf.get_cf(ceBulk.atoms) eci = {name:1.0 for name in corrfuncs.keys()} calc = CE( ceBulk,eci ) for _ in range(n_concs): conc = np.random.rand(len(basis_elems))*0.97 conc /= np.sum(conc) conc_dict = {} for i in range(len(basis_elems)): conc_dict[basis_elems[i]] = conc[i] calc.set_composition(conc_dict) ref_cf = calc.get_cf() singlets = {} for key,value in ref_cf.items(): if ( key.startswith("c1") ): singlets[key] = value comp = calc.singlet2comp(singlets) dict_comp = "Ref {}. Computed {}".format(conc_dict,comp) for key in comp.keys(): self.assertAlmostEqual( comp[key], conc_dict[key], msg=dict_comp, places=1 ) calc.set_singlets(singlets) except Exception as exc: msg = str(exc) no_throw = False self.assertTrue( no_throw, msg=msg )
def test_binary_spacegroup( self ): if ( not has_ase_with_ce ): self.skipTest("ASE version does not have CE") return bs, db_name = get_bulkspacegroup_binary() cf = CorrFunction( bs ) cf_vals = cf.get_cf( bs.atoms ) ecis = {name:1.0 for name in cf_vals.keys()} calc = CE( bs, ecis ) bs.atoms.set_calculator( calc ) for i in range(25): if ( bs.atoms[i].symbol == "Al" ): new_symb = "Mg" old_symb = "Al" else: new_symb = "Al" old_symb = "Mg" calc.calculate( bs.atoms, ["energy"], [(i,old_symb,new_symb)] ) updated_cf = calc.get_cf() brute_force = cf.get_cf_by_cluster_names( bs.atoms, updated_cf.keys() ) for key,value in brute_force.items(): self.assertAlmostEqual( value, updated_cf[key] )
def init_bulk_crystal(self): conc = Concentration(basis_elements=[["Al", "Mg", "Si"]]) ceBulk = CEBulk(crystalstructure="fcc", a=4.05, size=[4, 4, 4], concentration=conc, db_name=db_name, max_cluster_size=2, max_cluster_dia=4.0) ceBulk.reconfigure_settings() ecis = get_example_ecis(bc=ceBulk) atoms = ceBulk.atoms.copy() calc = CE(atoms, ceBulk, ecis) return ceBulk, atoms
def init_bulk_crystal(self): max_dia_name = get_max_cluster_dia_name() size_arg = {max_dia_name: 4.05} conc = Concentration(basis_elements=[["Al", "Mg", "Si"]]) ceBulk = CEBulk(crystalstructure="fcc", a=4.05, size=[3, 3, 3], concentration=conc, db_name=db_name, max_cluster_size=3, **size_arg) ceBulk.reconfigure_settings() atoms = ceBulk.atoms.copy() calc = CE(atoms, ceBulk, ecis) return ceBulk, atoms
def init_bulk_crystal(self): conc_args = { "conc_ratio_min_1": [[2, 1, 1]], "conc_ratio_max_1": [[0, 2, 2]], } max_dia_name = get_max_cluster_dia_name() size_arg = {max_dia_name: 4.05} ceBulk = CEBulk(crystalstructure="fcc", a=4.05, size=[3, 3, 3], basis_elements=[["Al", "Mg", "Si"]], conc_args=conc_args, db_name=db_name, max_cluster_size=3, **size_arg) ceBulk.reconfigure_settings() calc = CE(ceBulk, ecis) ceBulk.atoms.set_calculator(calc) return ceBulk
def test_no_throw(self): if (not has_ase_with_ce): self.skipTest("The ASE version does not include the CE module!") return no_throw = True msg = "" try: db_name = "test_db.db" conc = Concentration(basis_elements=[["Al", "Mg"]]) ceBulk = CEBulk(crystalstructure="fcc", a=4.05, size=[3, 3, 3], concentration=conc, db_name=db_name, max_cluster_size=3, max_cluster_dia=4.5) ceBulk.reconfigure_settings() cf = CorrFunction(ceBulk) cf = cf.get_cf(ceBulk.atoms) ecis = {key: 0.001 for key in cf.keys()} atoms = ceBulk.atoms.copy() calc = Clease(ceBulk, cluster_name_eci=ecis) # Bug in the update atoms.set_calculator(calc) #ceBulk.atoms.set_calculator( calc ) mf = MeanFieldApprox(atoms, ceBulk) chem_pot = {"c1_0": -1.05} betas = np.linspace(1.0 / (kB * 100), 1.0 / (kB * 800), 50) G = mf.free_energy(betas, chem_pot=chem_pot) G = mf.free_energy(betas) # Try when chem_pot is not given U = mf.internal_energy(betas, chem_pot=chem_pot) U = mf.internal_energy(betas) Cv = mf.heat_capacity(betas, chem_pot=chem_pot) Cv = mf.heat_capacity(betas) atoms = ceBulk.atoms.copy() atoms[0].symbol = "Mg" atoms[1].symbol = "Mg" calc = CE(atoms, ceBulk, eci=ecis) #ceBulk.atoms.set_calculator(calc) # Test the Canonical MFA T = [500, 400, 300, 200, 100] canonical_mfa = CanonicalMeanField(atoms=atoms, T=T) res = canonical_mfa.calculate() except Exception as exc: no_throw = False msg = str(exc) self.assertTrue(no_throw, msg=msg)
def get_calc(self, lat): db_name = "test_db_{}.db".format(lat) conc = Concentration(basis_elements=[["Al", "Mg"]]) a = 4.05 ceBulk = CEBulk(crystalstructure=lat, a=a, size=[3, 3, 3], concentration=conc, db_name=db_name, max_cluster_size=3, max_cluster_dia=6.0) ceBulk.reconfigure_settings() cf = CorrFunction(ceBulk) corrfuncs = cf.get_cf(ceBulk.atoms) eci = {name: 1.0 for name in corrfuncs.keys()} atoms = ceBulk.atoms.copy() calc = CE(atoms, ceBulk, eci) atoms.set_calculator(calc) return atoms, ceBulk, eci
def test_network(self): if (not available): self.skipTest("ASE version does not have CE!") return msg = "" no_throw = True try: db_name = "test_db_network.db" conc = Concentration(basis_elements=[["Al", "Mg"]]) a = 4.05 ceBulk = CEBulk(crystalstructure="fcc", a=a, size=[3, 3, 3], concentration=conc, db_name=db_name, max_cluster_size=3, max_cluster_dia=4.5) ceBulk.reconfigure_settings() cf = CorrFunction(ceBulk) atoms = ceBulk.atoms.copy() cf = cf.get_cf(atoms) eci = {key: 0.001 for key in cf.keys()} calc = CE(atoms, ceBulk, eci=eci) trans_mat = ceBulk.trans_matrix for name, info in ceBulk.cluster_info[0].items(): if info["size"] == 2: net_name = name break obs = NetworkObserver(calc=calc, cluster_name=[net_name], element=["Mg"]) # Several hard coded tests calc.update_cf((0, "Al", "Mg")) size = 2 clusters = ceBulk.cluster_info[0][net_name]["indices"] for sub_clust in clusters: calc.update_cf((sub_clust[0], "Al", "Mg")) # Call the observer obs(None) res = obs.fast_cluster_tracker.get_cluster_statistics_python() self.assertEqual(res["cluster_sizes"][0], size) size += 1 obs.get_indices_of_largest_cluster_with_neighbours() os.remove("test_db_network.db") except Exception as exc: msg = "{}: {}".format(type(exc).__name__, str(exc)) no_throw = False self.assertTrue(no_throw, msg=msg)
def init_bulk_crystal(self): conc_args = { "conc_ratio_min_1": [[2, 1, 1]], "conc_ratio_max_1": [[0, 2, 2]], } ceBulk = CEBulk(crystalstructure="fcc", a=4.05, size=[4, 4, 4], basis_elements=[["Al", "Mg", "Si"]], conc_args=conc_args, db_name=db_name, max_cluster_size=2, max_cluster_dia=4.0) ceBulk.reconfigure_settings() ecis = get_example_ecis(bc=ceBulk) calc = CE(ceBulk, ecis) ceBulk.atoms.set_calculator(calc) return ceBulk
def get_calc(self, lat): db_name = "test_db_{}.db".format(lat) conc_args = { "conc_ratio_min_1": [[1, 0]], "conc_ratio_max_1": [[0, 1]], } a = 4.05 ceBulk = CEBulk(crystalstructure=lat, a=a, size=[3, 3, 3], basis_elements=[["Al", "Mg"]], conc_args=conc_args, db_name=db_name, max_cluster_size=3) ceBulk.reconfigure_settings() cf = CorrFunction(ceBulk) corrfuncs = cf.get_cf(ceBulk.atoms) eci = {name: 1.0 for name in corrfuncs.keys()} calc = CE(ceBulk, eci) return calc, ceBulk, eci
def test_raise_error_on_invalid_chem_pot(self): if not available: self.skipTest(avail_msg) bc = get_ternary_BC() ecis = get_example_ecis(bc=bc) ecis.pop('c1_1') atoms = bc.atoms.copy() calc = CE(atoms, bc, eci=ecis) atoms.set_calculator(calc) groups = [{"Al": 2}, {"Mg": 1, "Si": 1}] symbs = ["Al", "Mg", "Si"] T = 400 with self.assertRaises(InvalidChemicalPotentialError): PseudoBinarySGC(atoms, T, chem_pot=-0.2, symbols=symbs, groups=groups)
def test_save_load_calculator(self): if not has_ase_with_ce: self.skipTest("ASE does not have CE") calc, ceBulk, eci = self.get_calc("fcc") calc_fname = "calculator.json" calc.save(calc_fname) calc2 = CE.load(calc_fname) os.remove(calc_fname) self.assertEqual(calc.BC.cluster_info, calc2.BC.cluster_info) self.assertEqual(calc.eci, calc2.eci) self.assertEqual(calc.get_cf(), calc2.get_cf()) # Test to pickle a calculator import pickle pickled_string = pickle.dumps(calc) calc2 = pickle.loads(pickled_string) self.assertEqual(calc.BC.cluster_info, calc2.BC.cluster_info) self.assertEqual(calc.eci, calc2.eci) self.assertEqual(calc.get_cf(), calc2.get_cf())
def test_with_covariance_reac_crd(self): if not available: self.skipTest("ASE version does not have CE!") msg = "" no_throw = True try: bc = get_ternary_BC() atoms = bc.atoms.copy() ecis = get_example_ecis(bc=bc) calc = CE(atoms, bc, eci=ecis) #bc.atoms.set_calculator(calc) T = 200 nn_names = [name for name in bc.cluster_family_names if int(name[1]) == 2] mc = FixedNucleusMC( atoms, T, network_name=nn_names, network_element=["Mg", "Si"]) elements = {"Mg": 4, "Si": 4} mc.insert_symbol_random_places("Mg", num=1, swap_symbs=["Al"]) mc.grow_cluster(elements) conc_init = CovarianceCrdInitializer( fixed_nucl_mc=mc, matrix_element="Al", cluster_elements=["Mg", "Si"]) mc.runMC(steps=100, init_cluster=False) match, match_msg = self._spherical_nano_particle_matches(conc_init) self.assertTrue(match, msg=match_msg) except Exception as exc: no_throw = False msg = str(exc) self.assertTrue(no_throw, msg=msg)
class PopulationVariance(object): """ Object that estimates the covariance and the mean of all the correlation functions in the population """ def __init__(self, BC): self.bc = BC cf_obj = CorrFunction(self.bc) self.init_cf = cf_obj.get_cf(self.bc.atoms) ecis = {key: 1.0 for key in self.init_cf.keys()} # ECIs do not matter here self.calc = CE(self.bc, ecis, initial_cf=self.init_cf) self.bc.atoms.set_calculator(self.calc) self.elements = self.bc.basis_elements[ 0] # This should be updated to handle different site types self.status_every_sec = 30 N = len(ecis.keys()) - 1 self.cov_matrix = np.zeros((N, N)) self.exp_value = np.zeros(N) def swap_random_atoms(self): """ Changes the symbol of a random atom """ indx = np.random.randint(low=0, high=len(self.bc.atoms)) symb = self.bc.atoms[indx].symbol new_symb = self.elements[np.random.randint(low=0, high=len(self.elements))] system_change = [(indx, symb, new_symb)] self.bc.atoms._calc.calculate(self.bc.atoms, ["energy"], system_change) def estimate(self, n_probe_structures=10000, fname=""): """ Estimate the covariance matrix """ if (fname != ""): if (not fname.endswith(".json")): raise ValueError( "The program is going to write a json file so the file extension should be .json" ) step = 0 cfs = [] cur_time = time.time() while (step < n_probe_structures): step += 1 if (time.time() - cur_time > self.status_every_sec): print("Step {} of {}".format(step, n_probe_structures)) cur_time = time.time() for i in range(len(self.bc.atoms)): self.swap_random_atoms() new_cfs = self.calc.get_cf() cf_array = [ new_cfs[key] for key in self.init_cf.keys() if key != "c0" ] # Make sure that the order is the same as in init_cf self.update_cov_matrix(cf_array) cfs = np.array(cfs) cov = self.cov_matrix / n_probe_structures mu = self.exp_value / n_probe_structures cov -= np.outer(mu, mu) return cov, mu def array2dict(self, cov, mu): """ Converts an array to a dictionary """ # Create dictionaries keys = self.init_cf.keys() del keys[keys.index("c0")] mu_dict = {keys[i]: mu[i] for i in range(len(keys))} cov_dict = {key: {} for key in keys} for i in range(len(keys)): for j in range(len(keys)): cov_dict[keys[i]][keys[j]] = cov[i, j] return cov_dict, mu_dict def update_cov_matrix(self, new_cfs): """ Updates the covariance matrix """ outer = np.outer(new_cfs, new_cfs) self.cov_matrix += outer self.exp_value += np.array(new_cfs) def save(self, eigval, eigvec, fname="eigenvectors.h5", fraction=0.95): """ Store the lowest fraction of the eigenvectors """ srt_indx = np.argsort(eigval)[::-1] eigval_srt = [eigval[indx] for indx in srt_indx] eigvec_srt = np.array([eigvec[:, indx] for indx in srt_indx]).T cumsum_eig = np.cumsum(eigval_srt) tot_sum = np.sum(eigval_srt) relative_sum = cumsum_eig / tot_sum max_indx = np.argmin(np.abs(relative_sum - fraction)) matrix = eigvec_srt[:, :max_indx] eigen = eigval_srt[:max_indx] with h5.File(fname, 'w') as hf: dset_vec = hf.create_dataset("eigenvectors", data=matrix) dset_eigen = hf.create_dataset("eigenvalues", data=eigen) dset_eigen.attrs["fraction"] = fraction print("Result written to {}".format(fname)) def diagonalize(self, cov, plot=False): """ Diagonalize the covariance matrix """ eigval, eigvec = np.linalg.eigh(cov) # Sort accorting to eigenvalues srt_indx = np.argsort(eigval)[::-1] eigval_srt = [eigval[indx] for indx in srt_indx] eigvec_srt = np.array([eigvec[:, indx] for indx in srt_indx]).T cumsum_eig = np.cumsum(eigval_srt) tot_sum = np.sum(eigval_srt) if (plot): x_val = np.arange(len(eigval)) fig = plt.figure() ax = fig.add_subplot(1, 1, 1) ax.plot(x_val, cumsum_eig / tot_sum, ls="steps") ax.set_xlabel("Number of eigenvectors") ax.set_ylabel("Normalized variance") return eigval, eigvec def plot_eigen(self, eigenvalues, eigenvectors): """ Creates a visualization of the eigenvectors and the eigenvalues NOTE: Eigenvalues and eigenvectors must NOT be sorted. They have to be given in the same order as returned by diagonalize """ keys = self.init_cf.keys() del keys[keys.index("c0")] srt_indx = np.argsort(eigenvalues)[::-1] key_srt = [keys[indx] for indx in srt_indx] eigval_srt = [eigenvalues[indx] for indx in srt_indx] eigvec_srt = np.array([eigenvectors[:, indx] for indx in srt_indx]).T grid_kw = {"hspace": 0.0, "height_ratios": [1, 4]} fig, ax = plt.subplots(nrows=2, sharex=True, gridspec_kw=grid_kw) x = np.arange(len(eigvec_srt)) cumsum = np.cumsum(eigval_srt) tot_sum = np.sum(eigval_srt) ax[0].plot(x, cumsum / tot_sum, ls="steps") keys_srt, eigvec_srt = self.sort_eigenvectors_by_size(keys, eigvec_srt) #ax[1].imshow( eigvec_srt, cmap="coolwarm", aspect="auto" ) print(eigvec_srt[:, 0]) # Separation lines to separate different sizes hlines = [] size = 2 for i, name in enumerate(keys_srt): prefix = "c{}".format(size) if (name.startswith(prefix)): hlines.append(i) size += 1 for line in hlines: ax[1].axhline(line) return fig def sort_eigenvectors_by_size(self, keys, eigvec): """ Sort the eigenvector values """ srt_indx = np.argsort(keys) keys_srt = [keys[indx] for indx in srt_indx] eigvec_srt = np.array([eigvec[indx, :] for indx in srt_indx]) return keys_srt, eigvec_srt