示例#1
0
def new_by_switch_atoms_on_substrate(ind_in: Individual):
    # returns individual made by switch of two random atoms on particular substrate
    struct = ind_in.get_relaxed_structure().copy()
    substrate = read_vasp("POSCAR.substrate")
    s = surface(substrate, (0, 0, 1), 1, vacuum=0., tol=1e-10)
    cell = s.get_cell()
    cell[2][2] = 25.
    s.set_cell(cell)
    z_max = -100.
    positions = s.get_positions()
    for pos in positions:
        z = pos[2]
        if z > z_max:
            z_max = z
    # print("z_max", z_max)
    chem_sym = struct.get_chemical_symbols()
    Nat = len(chem_sym)
    flag = 0
    while flag == 0:
        indx1 = randrange(Nat)
        indx2 = randrange(Nat)
        z1 = struct.get_positions()[indx1][2]
        z2 = struct.get_positions()[indx2][2]
        # print(z1,z2)
        if indx2 != indx1 and chem_sym[indx1] != chem_sym[
                indx2] and z1 > z_max and z2 > z_max:
            # print(indx1,indx2)
            chem_sym_new = swap_positions(chem_sym, indx1, indx2)
            struct.set_chemical_symbols(chem_sym_new)
            flag = 1
    ind = Individual(struct, -1)
    return ind
示例#2
0
def new_by_shift_coordinate(ind_in: Individual):
    # returns individual made by random change of one coordinate
    struct = ind_in.get_relaxed_structure().copy()
    Nat = len(struct.get_chemical_symbols())
    positions = struct.get_scaled_positions()
    delta = uniform(-0.1, 0.1)
    indx_at = randrange(Nat)
    indx_coord = randrange(3)
    positions[indx_at][indx_coord] = positions[indx_at][indx_coord] + delta
    struct.set_scaled_positions(positions)
    ind = Individual(struct)
    return ind
示例#3
0
 def init_population_random_on_substrate(self):
     print("generating initial population on substrate randomly ...")
     population = []
     i = 1
     while i <= self.Npop:
         struct = random_structure_on_substrate(self.chem_form, self.amin,
                                                self.amax, self.dmin,
                                                self.model_file)
         individual = Individual(struct)
         individual.origin = "new ind. random on substrate from scratch"
         population.append(individual)
         i = i + 1
     return population
示例#4
0
def get_population_db(dbfile, ngen):
    population = []
    conn = sqlite3.connect(dbfile)
    cur = conn.cursor()

    cur.execute("SELECT * FROM individuals WHERE ngen=?", [ngen])
    rows = cur.fetchall()

    for row in rows:
        struct = pickle.loads(row[4])
        ind = Individual(struct)
        population.append(ind)

    return population
示例#5
0
def get_best_individual(population):
    e_tot_min = 0.
    for ind in population:
        try:
            e_tot = ind.e_tot
            struct = ind.get_relaxed_structure()
        except:
            e_tot = 1000.
        if e_tot < e_tot_min:
            struct_best = struct
            e_tot_min = e_tot
    print("e_tot_min: " + str(e_tot_min))
    individual = Individual(struct_best)
    return individual
示例#6
0
def new_by_switch_atoms(ind_in: Individual):
    # returns individual made by switch of two random atoms
    struct = ind_in.get_relaxed_structure().copy()
    chem_sym = struct.get_chemical_symbols()
    Nat = len(chem_sym)
    if Nat > 2:
        indx1 = randrange(Nat)
        flag = 0
        while flag == 0:
            indx2 = randrange(Nat)
            if indx2 != indx1 and chem_sym[indx1] != chem_sym[indx2]:
                chem_sym_new = swap_positions(chem_sym, indx1, indx2)
                struct.set_chemical_symbols(chem_sym_new)
                flag = 1
    ind = Individual(struct, -1)
    return ind
示例#7
0
def new_by_shift_coordinates(ind_in: Individual):
    # returns individual made by random change of x,y coordinates by random delta
    struct = ind_in.get_relaxed_structure().copy()
    Nat = len(struct.get_chemical_symbols())
    positions = struct.get_scaled_positions()
    delx = uniform(0., 0.2)
    dely = uniform(0., 0.2)
    indx1 = randrange(Nat)
    indx2 = indx1
    while indx2 == indx1:
        indx2 = randrange(Nat)
    positions[indx1][0] = positions[indx1][0] + delx
    positions[indx1][1] = positions[indx1][1] + dely
    positions[indx2][0] = positions[indx2][0] - delx
    positions[indx2][1] = positions[indx2][1] - dely
    struct.set_scaled_positions(positions)
    ind = Individual(struct, -1)
    return ind
示例#8
0
 def init_population_random(self, model=1):
     # inits random population with model verification, returns list of individuals
     # verification regards "bad" struxtures
     print("generating initial population randomly ...")
     population = []
     i = 1
     while i <= self.Npop:
         if model == 0:
             struct = random_structure(self.chem_form, self.amin, self.amax,
                                       self.dmin)
         if model == 1:
             struct = random_structure_model(self.chem_form, self.amin,
                                             self.amax, self.dmin,
                                             self.model_file)
         individual = Individual(struct)
         individual.origin = "new ind. random from scratch"
         population.append(individual)
         i = i + 1
     return population
示例#9
0
def new_by_random_coordinates(ind_in: Individual):
    # returns individual made by changing all coordinates randomly (cell is intact)
    struct = ind_in.get_relaxed_structure().copy()
    Nat = len(struct.get_chemical_symbols())
    flag = 0
    while flag == 0:
        positions = []
        #
        for i in range(Nat):
            pos = [uniform(0., 0.90), uniform(0., 0.90), uniform(-0.1, 0.1)]
            positions.append(pos)
        #
        struct.set_scaled_positions(positions)
        positions_ang = struct.get_positions()
        # print(positions_ang)
        flag = check_dist(Nat, positions_ang, dmin=1.4)
        # print(flag)
    # print(struct)
    ind = Individual(struct, -1)
    return ind
示例#10
0
 def init_population_random_group(self):
     # inits pyxtal random population with model verification, returns list of individuals
     print(
         "generating initial population randomly but using group theory ..."
     )
     population = []
     i = 1
     while i <= self.Npop:
         struct = random_structure_group(self.chem_sym,
                                         self.stoichio,
                                         thickness=3.0,
                                         tol_factor=0.9,
                                         model_file=self.model_file,
                                         dmin=self.dmin,
                                         Natt=100)
         individual = Individual(struct)
         individual.origin = "new ind. random from scratch"
         population.append(individual)
         i = i + 1
     return population
示例#11
0
def get_c2db_prototypes(dbfile,
                        prototype,
                        stability=False,
                        smagstate=False,
                        sgap=0):
    # returns list of Individuals from c2db
    # Connect to the database - ase interface
    db = ase.db.connect(dbfile)
    # Connect to the database - sqlite3 interface
    conn = sqlite3.connect(dbfile)
    cur = conn.cursor()
    cur.execute('SELECT SQLITE_VERSION()')
    data = cur.fetchone()
    print("SQLite version: " + str(format(data)))

    # nstruct = 0
    # magstate = 'FM'
    dyn_key = 'dynamic_stability_level'
    th_key = 'thermodynamic_stability_level'
    # gap_key = 'gap'

    # rows = db.select('magstate=FM')
    if prototype != "":
        query = 'class=' + prototype
        # print(query)
        rows = db.select(query)
    if prototype == "":
        # rows = db.select('calculator=gpaw')
        rows = db.select('gap>-1')
    print(rows)

    individuals = []

    for row in rows:
        id = row.get("id")
        e_tot = row.get("energy")
        label = row.get('formula')
        gap = row.get('gap')
        #print(gap)
        magstate = row.get('magstate')
        magmom = row.get('magmom')
        positions = row.get('positions')
        cell = row.get('cell')
        hform = row.get('hform')
        e_tot = row.get('energy')

        # Stability info - not implemented is ase interface
        cur.execute(
            "SELECT * FROM number_key_values WHERE id=:id AND key=:dyn_key", {
                "id": id,
                "dyn_key": dyn_key
            })
        data = cur.fetchone()
        if data is not None:
            stability_dyn = data[1]
        else:
            stability_dyn = 0.
        cur.execute(
            "SELECT * FROM number_key_values WHERE id=:id AND key=:th_key", {
                "id": id,
                "th_key": th_key
            })
        data = cur.fetchone()
        if data is not None:
            stability_th = data[1]
        else:
            stability_th = 0.

        if stability == False:
            struct_ase = Atoms(label,
                               positions=positions,
                               cell=cell,
                               pbc=np.array([True, True, True], dtype=bool))
            Nat = len(struct_ase.get_chemical_symbols())
            ind = Individual(struct_ase)
            ind.set_e_tot(e_tot / float(Nat))
            ind.set_mmtot(magmom)
            ind.set_hform(hform)
            individuals.append(ind)

        if stability == True and smagstate == False and sgap == 0:
            if stability_th == 3.0:
                struct_ase = Atoms(label,
                                   positions=positions,
                                   cell=cell,
                                   pbc=np.array([True, True, True],
                                                dtype=bool))
                Nat = len(struct_ase.get_chemical_symbols())
                ind = Individual(struct_ase)
                ind.set_e_tot(e_tot / float(Nat))
                ind.set_mmtot(magmom)
                ind.set_hform(hform)
                individuals.append(ind)

        if stability == True and smagstate == False and sgap > 0:
            if stability_th == 3.0 and gap > 0.:
                struct_ase = Atoms(label,
                                   positions=positions,
                                   cell=cell,
                                   pbc=np.array([True, True, True],
                                                dtype=bool))
                Nat = len(struct_ase.get_chemical_symbols())
                ind = Individual(struct_ase)
                ind.set_e_tot(e_tot / float(Nat))
                ind.set_mmtot(magmom)
                ind.set_hform(hform)
                individuals.append(ind)

        if stability == True and smagstate == True and smagstate == "FM":
            if stability_dyn == 3.0 and stability_th == 3.0 and abs(
                    float(magmom)) > 0.1:
                struct_ase = Atoms(label,
                                   positions=positions,
                                   cell=cell,
                                   pbc=np.array([True, True, True],
                                                dtype=bool))
                Nat = len(struct_ase.get_chemical_symbols())
                ind = Individual(struct_ase)
                ind.set_e_tot(e_tot / float(Nat))
                ind.set_mmtot(magmom)
                ind.set_hform(hform)
                individuals.append(ind)

    return individuals
示例#12
0
def new_by_switch_layers(ind_in: Individual):
    # returns individual made by switch of two random layers
    struct = ind_in.get_relaxed_structure().copy()
    write(filename="POSCAR.in.in", images=struct, format="espresso-in")
    layers = get_layers(struct)
    nlay = len(layers)
    if nlay > 1:
        # random indexes
        indx1 = randrange(nlay)
        flag = 0
        while flag == 0:
            indx2 = randrange(nlay)
            if indx2 != indx1:
                flag = 1
        layer1 = layers[indx1]
        layer2 = layers[indx2]
        print("switching layers " + str(indx1 + 1) + " and " + str(indx2 + 1))
        pos = struct.get_positions()
        chem = struct.get_chemical_symbols()
        cell = struct.get_cell()
        new_pos = []
        new_chem = []
        # 1 - setting all other atoms
        n = len(chem)
        for i in range(n):
            if i not in layer1 and i not in layer2:
                # print(i)
                new_pos.append(pos[i])
                new_chem.append(chem[i])
        # 2 - calculate shift between layers
        z1 = []
        z2 = []
        for i in layer1:
            z = pos[i][2]
            z1.append(z)
        for i in layer2:
            z = pos[i][2]
            z2.append(z)
        min1 = max(z1)
        min2 = max(z2)
        zshift = min1 - min2
        # 3 - setting layer1 and layer2 atoms with shift
        for i in range(n):
            if i in layer1:
                # print(i)
                if min1 > min2:
                    pos[i][2] = pos[i][2] + zshift
                if min1 < min2:
                    pos[i][2] = pos[i][2] - zshift
                new_pos.append(pos[i])
                new_chem.append(chem[i])
            if i in layer2:
                # print(i)
                if min1 > min2:
                    pos[i][2] = pos[i][2] - zshift
                if min1 < min2:
                    pos[i][2] = pos[i][2] + zshift
                new_pos.append(pos[i])
                new_chem.append(chem[i])
        st = ""
        for chem in new_chem:
            st = st + chem
        new_struct = Atoms(st)
        new_struct.set_cell(cell)
        new_pos2 = np.asarray(new_pos)
        new_struct.set_positions(new_pos2)
        ind = Individual(new_struct)
        write(filename="POSCAR.out.in",
              images=new_struct,
              format="espresso-in")
    else:
        ind = Individual(struct)
        print("warning: only one layer, no change in structure!")
    return ind
示例#13
0
 def generate_new_population_alg2_substrate(self, population):
     # generates new population using algorithm no. 2
     print("")
     print("generating new population with softmutation ...")
     print("")
     new_population = []
     population.sort()
     Npop = self.Npop
     adapt = AseAtomsAdaptor()
     model = MEGNetModel.from_file(self.model_file)
     for i in range(int(Npop / 4)):  # 1/4 of population by atoms switch
         indx = randrange(Npop /
                          4)  # +1 # using only best 25% of population
         print("-------------------------------")
         print("new ind. from no. " + str(indx) + " by atoms switch")
         individual = new_by_switch_atoms_on_substrate(population[indx])
         individual.origin = "new ind. from no. " + str(
             indx) + " by atoms switch"
         new_population.append(individual)
     for i in range(int(Npop /
                        4)):  # 1/4 of population by kind of softmutation
         indx = randrange(Npop /
                          4)  # +1 # using only best 25% of population
         print("-------------------------------")
         print("new ind. from no. " + str(indx) + " by softmutation")
         ind_in = population[indx]
         structure_ase = ind_in.get_relaxed_structure().copy()
         structure_pymatgen = adapt.get_structure(structure_ase)
         e_tot_in = model.predict_structure(structure_pymatgen)
         e_tot_min = e_tot_in
         flag = 0
         for i in range(100):
             individual = new_by_shift_coordinate(population[indx])
             structure_ase = individual.get_init_structure().copy()
             structure_pymatgen = adapt.get_structure(structure_ase)
             try:
                 e_tot = model.predict_structure(structure_pymatgen)
             except:
                 e_tot = 0.
                 print("isolated molecule exception handled")
             if e_tot < e_tot_min:
                 flag = 1
                 e_tot_min = e_tot
                 ind_out = individual
         ind_out.origin = "new ind. from no. " + str(
             indx) + " by softmutation"
         if flag == 1:
             new_population.append(ind_out)
             print("softmutate energy gain: " + str(e_tot_min - e_tot_in))
         if flag == 0:
             new_population.append(ind_in)
     for i in range(int((Npop / 2) - 1)):
         # 1/2 of population (minus one) by new random structures, pyxtal+model
         # indx = randrange(Npop/2)+1
         print("-------------------------------")
         print("new ind. random from scratch")
         struct = random_structure_group(self.chem_sym,
                                         self.stoichio,
                                         thickness=3.0,
                                         tol_factor=0.9,
                                         model_file=self.model_file,
                                         dmin=self.dmin,
                                         Natt=RANDOM_ATTEMPTS)
         individual = Individual(struct)
         individual.origin = "new ind. random from scratch"
         new_population.append(individual)
     best_ind = get_best_individual(
         population)  # last one is the best in the current population
     best_ind.origin = "kept best"
     new_population.append(best_ind)
     return new_population