Esempio n. 1
0
def change_cell_length(atoms, space_group):

    #print(atoms.get_positions())
    #print(atoms.get_atomic_numbers())
    name = get_name(atoms.get_atomic_numbers())
    #print(name)
    molecule1, molecule2, molecule3, molecule4 = molecule_lists(atoms)[0], molecule_lists(atoms)[1], molecule_lists(atoms)[2], molecule_lists(atoms)[3]  # [1,5,9,13,17,21,etc]
    #print("molecule1: ", molecule1)
    #print(molecule2)
    #print(molecule3)
    #print(molecule4)
    scaled_positions = atoms.get_scaled_positions()
    molecule1_scaled_positions = np.array([scaled_positions[i] for i in molecule1])
    #print("molecule1_scaled_positions: ", molecule1_scaled_positions)
    molecule2_scaled_positions = np.array([scaled_positions[i] for i in molecule2])
    molecule3_scaled_positions = np.array([scaled_positions[i] for i in molecule3])
    molecule4_scaled_positions = np.array([scaled_positions[i] for i in molecule4])
    cell_params = atoms.get_cell()
    #print(atoms.get_cell())
    a_vector, b_vector, c_vector = cell_params[0], cell_params[1], cell_params[2]
    molecule1_vectors = np.array([faction[0] * a_vector + faction[1] * b_vector + faction[2] * c_vector for faction in molecule1_scaled_positions])
    #print("molecule1_vectors: ", molecule1_vectors)
    molecule2_vectors = np.array([faction[0] * a_vector + faction[1] * b_vector + faction[2] * c_vector for faction in molecule2_scaled_positions])
    molecule3_vectors = np.array([faction[0] * a_vector + faction[1] * b_vector + faction[2] * c_vector for faction in molecule3_scaled_positions])
    molecule4_vectors = np.array([faction[0] * a_vector + faction[1] * b_vector + faction[2] * c_vector for faction in molecule4_scaled_positions])
    new_atoms = atoms.copy()
    new_atoms.set_cell(cell_params + np.array([[3.0, 0, 0],[0, 3.0, 0],[0.0, 0, 3.0]]), scale_atoms=True)
    new_cell_params = new_atoms.get_cell()
    print("first atoms: ", new_atoms.get_positions()[0])
    #print("new_cell_params: ", new_cell_params)
    new_a_vector, new_b_vector, new_c_vector = new_cell_params[0], new_cell_params[1], new_cell_params[2]
    new_scaled_positions_molecule1 = get_position_for_molecule(molecule1_vectors, new_a_vector, new_b_vector, new_c_vector)
    #print("new_scaled_positions_molecule1: ", new_scaled_positions_molecule1)
    new_scaled_positions_molecule2 = get_position_for_molecule(molecule2_vectors, new_a_vector, new_b_vector, new_c_vector)
    new_scaled_positions_molecule3 = get_position_for_molecule(molecule3_vectors, new_a_vector, new_b_vector, new_c_vector)
    new_scaled_positions_molecule4 = get_position_for_molecule(molecule4_vectors, new_a_vector, new_b_vector, new_c_vector)

    #print("get_symop(): ", space_group.get_symop())
    sites = []
    for r1, r2, r3, r4 in zip(new_scaled_positions_molecule1, new_scaled_positions_molecule2, new_scaled_positions_molecule3, new_scaled_positions_molecule4):
        sites.append(r1)
        sites.append(r2)
        sites.append(r3)
        sites.append(r4)

    new_positions = np.array([faction[0] * new_a_vector + faction[1] * new_b_vector + faction[2] * new_c_vector for faction in sites])
    #print(new_positions - atoms.get_positions())
    #print(new_positions)
    writer =  Atoms(name,
                    positions=new_positions,
                    cell=new_atoms.get_cell(),
                    pbc=[1,1,1])

    #for i in molecule3:
    #    print(writer.get_distances(i, molecule3) - atoms.get_distances(i, molecule3))
    #print(writer.get_cell())

    return writer
Esempio n. 2
0
def rigid_body_movement(atoms):

    ret_molecule_lists = molecule_lists(atoms)
    x_com = get_com(atoms, ret_molecule_lists)
    print("x_com: ", x_com)
    F = np.matrix([[1,0,0],[0,1,0],[0,0,1]])
    delta_a, delta_b, delta_c = random_draw(0.1,0.1), random_draw(0.1,0.1), random_draw(0.1,0.1)
    new_F = F + np.matrix([[delta_a, 0, 0],[0, delta_b, 0],[0, 0, delta_c]])
    X = atoms.get_positions()
    x_com_new = np.matmul(x_com, new_F)
    L = atoms.get_cell()
    L_new = np.matmul(L, new_F)
    atoms.set_cell(L_new, scale_atoms=False)

#imolec, molec:  0 [1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81]
#imolec, molec:  1 [2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62, 66, 70, 74, 78, 82]
#imolec, molec:  2 [3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63, 67, 71, 75, 79, 83]
#imolec, molec:  3 [4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84]

    for imolec, molec in enumerate(ret_molecule_lists):
        print("imolec, molec: ", imolec, molec)
        for j in molec:
            for i in [0, 1, 2]:
                X[j-1, i] += (x_com_new[imolec, i] - x_com[imolec, i]) 
                #X[j-1, i] += x_com_new[imolec, i]

    atoms.set_positions(X)

    return atoms
Esempio n. 3
0
def generate_cell_length_c_frame(atoms,
                                 molecule1_atoms_index,
                                 space_group,
                                 sigma=0.1):

    name = get_name(atoms.get_atomic_numbers())
    st = ase_atoms_to_structure(atoms)
    my_atoms = atoms.copy()
    my_atoms.set_positions(st.getXYZ())
    molecules = molecule_lists(my_atoms)
    old_positions = my_atoms.get_positions()
    molecule1_vectors = np.array([old_positions[i] for i in molecules[0]])

    # set the perturbation
    new_atoms = my_atoms.copy()
    a, b, c, alpha, beta, gamma = my_atoms.get_cell_lengths_and_angles()
    if a != b and b != c and c != a:
        new_a, new_b, new_c = a, b, c + random_draw(sigma)
    elif a != b and b == c:
        new_a, new_c = a, c + random_draw(sigma)
        new_b = new_c
    elif a != b and a == c:
        new_c, new_b = c + random_draw(sigma), b
        new_a = new_c
    elif a == b and a != c:
        new_b, new_c = b, c + random_draw(sigma)
        new_a = new_b
    else:
        new_c = c + random_draw(sigma)
        new_a = new_c
        new_b = new_c

    # scaled_atoms = True
    new_atoms.set_cell([new_a, new_b, new_c, alpha, beta, gamma],
                       scale_atoms=True)
    new_cell_params = new_atoms.get_cell()
    new_a_vector, new_b_vector, new_c_vector = new_cell_params[
        0], new_cell_params[1], new_cell_params[2]
    new_molecule1_vectors = get_xyz_after_move(my_atoms.get_positions()[0],
                                               new_atoms.get_positions()[0],
                                               molecule1_vectors)

    sites = []
    for pos in new_molecule1_vectors:
        for rot, trans in space_group.get_symop():
            trans_a, trans_b, trans_c = trans[:]
            site = np.dot(
                rot, pos
            ) + trans_a * new_a_vector + trans_b * new_b_vector + trans_c * new_c_vector
            sites.append(site)
    new_positions = np.array(sites)

    ret_atoms = Atoms(name,
                      positions=new_positions,
                      cell=new_atoms.get_cell(),
                      pbc=[1, 1, 1])

    return ret_atoms
def move_molecule1(atoms, space_group):

    print("atoms.get_distance(1,5): ",
          atoms.get_distance(1, 5, mic=False, vector=True))
    print("atoms.get_distance(1,21): ",
          atoms.get_distance(1, 21, mic=False, vector=True))
    a, b, c, alpha, beta, gamma = atoms.get_cell_lengths_and_angles()
    X = atoms.get_positions()
    old_scaled_position = atoms.get_scaled_positions()
    print("a, b, c, alpha, beta, gamma: ", a, b, c, alpha, beta, gamma)
    #print("X: ", X)
    #print("old_scaled_position: ", old_scaled_position)
    molecule1 = molecule_lists(atoms)[0]
    st = ase_atoms_to_structure(atoms)
    x_com1 = center_of_mass(st, molecule1)
    X_molecule1 = np.array([X[x - 1] for x in molecule1])
    #print("X_molecule1: ", X_molecule1)

    F = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
    delta_a, delta_b, delta_c = random_draw(0.1, 0.1), random_draw(
        0.1, 0.1), random_draw(0.1, 0.1)
    new_F = F + np.array([[delta_a, 0, 0], [0, delta_b, 0], [0, 0, delta_c]])
    x_com1_new = np.dot(x_com1, new_F)

    diff_com = x_com1_new - x_com1
    #print("diff_com: ", diff_com)

    new_X = []

    for i, row in enumerate(X):
        if i + 1 in molecule1:
            new_X.append(row + diff_com)
        else:
            new_X.append(row)

    L = atoms.get_cell()
    new_L = np.dot(L, new_F)

    new_atoms = atoms.copy()
    new_atoms.set_positions(new_X)
    new_atoms.set_cell(new_L, scale_atoms=False)

    scaled_positions = new_atoms.get_scaled_positions()
    molecule1_scaled_positions = [scaled_positions[i - 1] for i in molecule1]
    final_scaled_positions = get_equivalent_sites(molecule1_scaled_positions,
                                                  space_group)
    #print("final_scaled_positions: ", final_scaled_positions)
    new_atoms.set_scaled_positions(final_scaled_positions)
    print("new_atoms.get_distance(1,5): ",
          new_atoms.get_distance(1, 5, mic=False, vector=True))
    print("new_atoms.get_distance(1,21): ",
          new_atoms.get_distance(1, 21, mic=False, vector=True))

    return new_atoms
def generate_perturb(atoms):
    atoms_input = atoms.copy()
    ret_atoms_cell_length = generate_cell_length_frame(atoms_input,
                                                       molecule1_atoms_index,
                                                       space_group, 2.0)
    print("after cell length ", molecule_lists(ret_atoms_cell_length))
    ret_atoms_cell_angle = generate_cell_angle_frame(ret_atoms_cell_length,
                                                     molecule1_atoms_index,
                                                     space_group, 0.1)
    print("after cell angle ", molecule_lists(ret_atoms_cell_angle))
    ret_atoms_rotation = generate_rotation_frame(ret_atoms_cell_angle,
                                                 molecule1_atoms_index,
                                                 space_group, 0.1)
    print("after rotation ", molecule_lists(ret_atoms_rotation))
    ret_atoms_translate = generate_translate_frame(ret_atoms_rotation,
                                                   molecule1_atoms_index,
                                                   space_group, 0.1)
    print("after translation ", molecule_lists(ret_atoms_translate))
    ret_atoms = ret_atoms_translate.copy()

    return ret_atoms
Esempio n. 6
0
def generate_perturb(atoms_input):
    """
    For debug use
    """
    ret_atoms_cell_length_a = generate_cell_length_a_frame(
        atoms_input, molecule1_atoms_index, space_group, 10.0)
    print("after cell length a", molecule_lists(ret_atoms_cell_length_a))
    ret_atoms_cell_length_b = generate_cell_length_b_frame(
        ret_atoms_cell_length_a, molecule1_atoms_index, space_group, 10.0)
    print("after cell length b", molecule_lists(ret_atoms_cell_length_b))
    ret_atoms_cell_length_c = generate_cell_length_c_frame(
        ret_atoms_cell_length_b, molecule1_atoms_index, space_group, 10.0)
    print("after cell length b", molecule_lists(ret_atoms_cell_length_c))

    ret_atoms_cell_angle_beta = generate_cell_angle_beta_frame(
        ret_atoms_cell_length_c, molecule1_atoms_index, space_group, 5.0)
    print("after cell angle ", molecule_lists(ret_atoms_cell_angle_beta))

    ret_atoms_rotation = generate_rotation_frame(ret_atoms_cell_angle_beta,
                                                 molecule1_atoms_index,
                                                 space_group, 10.0)
    print("after rotation ", molecule_lists(ret_atoms_rotation))

    ret_atoms_translate = generate_translate_frame(ret_atoms_rotation,
                                                   molecule1_atoms_index,
                                                   space_group, 2.0)
    print("after translation ", molecule_lists(ret_atoms_translate))
    ret_atoms = ret_atoms_translate.copy()

    return ret_atoms
def change_cell_length(atoms, space_group):

    name = get_name(atoms.get_atomic_numbers())
    molecule1, molecule2, molecule3, molecule4 = molecule_lists(atoms)[0], molecule_lists(atoms)[1], molecule_lists(atoms)[2], molecule_lists(atoms)[3]  # [1,5,9,13,17,21,etc]
    scaled_positions = atoms.get_scaled_positions()
    molecule1_scaled_positions = np.array([scaled_positions[i] for i in molecule1])
    molecule2_scaled_positions = np.array([scaled_positions[i] for i in molecule2])
    molecule3_scaled_positions = np.array([scaled_positions[i] for i in molecule3])
    molecule4_scaled_positions = np.array([scaled_positions[i] for i in molecule4])
    cell_params = atoms.get_cell()
    a_vector, b_vector, c_vector = cell_params[0], cell_params[1], cell_params[2]
    molecule1_vectors = np.array([faction[0] * a_vector + faction[1] * b_vector + faction[2] * c_vector for faction in molecule1_scaled_positions])
    molecule2_vectors = np.array([faction[0] * a_vector + faction[1] * b_vector + faction[2] * c_vector for faction in molecule2_scaled_positions])
    molecule3_vectors = np.array([faction[0] * a_vector + faction[1] * b_vector + faction[2] * c_vector for faction in molecule3_scaled_positions])
    molecule4_vectors = np.array([faction[0] * a_vector + faction[1] * b_vector + faction[2] * c_vector for faction in molecule4_scaled_positions])
    new_atoms = atoms.copy()
    new_atoms.set_cell(cell_params + np.array([[3.0, 0, 0],[0, 3.0, 0],[0.0, 0, 3.0]]), scale_atoms=False)
    new_cell_params = new_atoms.get_cell()
    new_a_vector, new_b_vector, new_c_vector = new_cell_params[0], new_cell_params[1], new_cell_params[2]
    new_scaled_positions_molecule1 = get_position_for_molecule(molecule1_vectors, new_a_vector, new_b_vector, new_c_vector)
    print("new_scaled_positions_molecule1: ", new_scaled_positions_molecule1)
    exit()
def generate_cell_angle_frame(atoms,
                              molecule1_atoms_index,
                              space_group,
                              mu=0.1,
                              sigma=0.1):

    # get names and molecule idx
    name = get_name(atoms.get_atomic_numbers())
    st = ase_atoms_to_structure(atoms)
    my_atoms = atoms.copy()
    my_atoms.set_positions(st.getXYZ())
    molecules = molecule_lists(my_atoms)
    old_positions = my_atoms.get_positions()
    molecule1_vectors = np.array([old_positions[i] for i in molecules[0]])

    # set the perturbation
    new_atoms = my_atoms.copy()
    a, b, c, alpha, beta, gamma = my_atoms.get_cell_lengths_and_angles()
    new_cell_params = [a, b, c]
    for angle in [alpha, beta, gamma]:
        if angle != 90:
            new_cell_params.append(angle + random_draw(mu, sigma))
        else:
            new_cell_params.append(angle)

    new_atoms.set_cell(new_cell_params, scale_atoms=True)

    new_cell_params = new_atoms.get_cell()
    new_a_vector, new_b_vector, new_c_vector = new_cell_params[
        0], new_cell_params[1], new_cell_params[2]
    new_molecule1_vectors = get_xyz_after_move(my_atoms.get_positions()[0],
                                               new_atoms.get_positions()[0],
                                               molecule1_vectors)

    sites = []
    for pos in new_molecule1_vectors:
        for rot, trans in space_group.get_symop():
            trans_a, trans_b, trans_c = trans[:]
            site = np.dot(
                rot, pos
            ) + trans_a * new_a_vector + trans_b * new_b_vector + trans_c * new_c_vector
            sites.append(site)
    new_positions = np.array(sites)

    ret_atoms = Atoms(name,
                      positions=new_positions,
                      cell=new_atoms.get_cell(),
                      pbc=[1, 1, 1])

    return ret_atoms
def rigid_body_movement(atoms):

    ret_molecule_lists = molecule_lists(atoms)
    molecule1 = ret_molecule_lists[0]
    atom1_index = molecule1[0]
    scaled_position = atoms.get_scaled_positions(wrap=True)

    print("atom1_index: ", atom1_index)
    #    print("atoms scaled position: ", scaled_position)
    print("atoms1 scaled position: ", scaled_position[atom1_index - 1])

    atom2_index = molecule1[1]
    print("atoms2 scaled position: ", scaled_position[atom2_index - 1])
    a, b, c, alpha, beta, gamma = atoms.get_cell_lengths_and_angles()

    return atoms
Esempio n. 10
0
def Monte_Carlo(atoms,
                calculator,
                space_group,
                step_size,
                perturbation,
                counter,
                molecule1_in_cell=[],
                MC_steps=1000,
                debug=False):
    """
    atoms: atoms class in ASE module
    perturbation: str represent cell and xyz changes
    counter: int for writing files

    return a new frame base on:

    if new_E < old_E:
        accepted, continue MD with new frame
    elif new_E > old_E:
        delta_Emn = new_E - old_E
        p = exp(-delta_Emn/kBT)
        generate a random number nu(0,1)
        if p > nu:
            accepted, continue MD with new frame
        else:
            rejected, continue MD with old frame
    """
    a, b, c, alpha, beta, gamma = atoms.get_cell_lengths_and_angles()
    xyz = atoms.get_positions()
    fraction = atoms.get_scaled_positions()
    MC_trace[counter] = {}
    MC_trace[counter]['a'] = a
    MC_trace[counter]['b'] = b
    MC_trace[counter]['c'] = c
    MC_trace[counter]['alpha'] = alpha
    MC_trace[counter]['beta'] = beta
    MC_trace[counter]['gamma'] = gamma
    MC_trace[counter]['xyz'] = xyz.tolist()
    MC_trace[counter]['fraction'] = fraction.tolist()

    old_atoms = atoms.copy()
    old_atoms.set_calculator(calculator)
    old_E = atoms.get_total_energy()

    if perturbation == "translate":
        new_atoms = generate_translate_frame(atoms, molecule1_in_cell,
                                             space_group, step_size)
    elif perturbation == "rotation":
        new_atoms = generate_rotation_frame(atoms, molecule1_in_cell,
                                            space_group, step_size)
    elif perturbation == "cell_length":
        new_atoms = generate_cell_length_frame(atoms, molecule1_in_cell,
                                               space_group, step_size)
    else:
        new_atoms = generate_cell_angle_frame(atoms, molecule1_in_cell,
                                              space_group, step_size)

    if (len(molecule_lists(new_atoms)) != len(molecule_lists(old_atoms))):
        print("%s move by %f to Frame %d Rejected due to clash!" %
              (perturbation, step_size, counter))
        outfile = "Rejected_clash_%d.cif" % counter
        ase_io.write(outfile, new_atoms)
        return old_atoms, "Rejected"

    new_atoms.set_calculator(calculator)
    new_E = new_atoms.get_total_energy()

    #print("old_E and new_E: ", old_E, new_E)
    if new_E < old_E:
        print("Frame %d Accepted!" % counter)
        if counter % 100 == 0 or MC_steps - counter < 100 or debug:
            outfile = "Accepted_%d.cif" % counter
            ase_io.write(outfile, new_atoms)
        return new_atoms, "Accepted"
    else:
        delta_Emn = new_E - old_E
        delta_Emn = delta_Emn * 23  # ev to kcal/mol
        p = math.exp(-delta_Emn / units.kB / 300)
        nu = random.uniform(0, 1)
        if p > nu:
            print("Frame %d Accepted!" % counter)
            if counter % 100 == 0 or MC_steps - counter < 100 or debug:
                outfile = "Accepted_%d.cif" % counter
                ase_io.write(outfile, new_atoms)
            return new_atoms, "Accepted"
        else:
            print("Frame %d Rejected!" % counter)
            return old_atoms, "Rejected"
Esempio n. 11
0
    ret_atoms_translate = generate_translate_frame(ret_atoms_rotation,
                                                   molecule1_atoms_index,
                                                   space_group, 2.0)
    print("after translation ", molecule_lists(ret_atoms_translate))
    ret_atoms = ret_atoms_translate.copy()

    return ret_atoms


if __name__ == "__main__":

    print("runing main function for debugging...")
    atoms = ase_io.read(sys.argv[1])
    spacegroup_number = sys.argv[2]
    molecule1_atoms_index = molecule_lists(atoms)[0]
    print(molecule_lists(atoms))
    print("molecule1_atoms_index: ", molecule1_atoms_index)
    if spacegroup_number:
        space_group = Spacegroup(int(spacegroup_number))
    else:
        space_group = spacegroup.get_spacegroup(atoms)
    print("before perturbation: ", space_group)
    # first enlarge cell and then change the anlge.
    #ret_atoms = ret_atoms_translate.copy()
    # atoms_input = atoms.copy()
    # ret_atoms = generate_perturb(atoms_input)
    # dummy input
    ret_atoms = Atoms('Au',
                      positions=[[0, 10 / 2, 10 / 2]],
                      cell=[10, 10, 10],
def main():

    args = parse_args()
    print("args", args)

    if args.implementation == TORCHANI:
        from torchani_calculator import torchani_calculator
        calculator = torchani_calculator(args.network_type)
    elif args.implementation == AES_ANI:
        from ani_ase import ani_ase_calculator
        calculator = ani_ase_calculator(args.network_type)
    elif args.implementation == KHAN:
        from khan_calculator import khan_calculator
        calculator = khan_calculator(args.network_type, args.khan_network,
                                     args.numb_networks)

    assert args.cif_file.endswith('.cif')

    print('debug? ', args.debug)
    atoms = ase_io.read(args.cif_file)
    numb_molecules = len(molecule_lists(atoms))
    print('number of molecules: ', numb_molecules)
    MC_stpes = args.MC
    space_group = Spacegroup(args.space_group)
    # step size in MC
    f1, f2, f3, f4, f5, f6, f7, f8 = args.MC_f1_f2_f3_f4_f5_f6_f7_f8
    perturbation_type = args.perturbation_type
    molecule1_in_cell = []
    for i in range(1, atoms.get_number_of_atoms()):
        if atom_belong_to_mol1(i, atoms):
            molecule1_in_cell.append(i)
    print("initial unit cell")
    print(atoms.cell)
    print("To do Monte Carlo for %d step." % MC_stpes)
    print("Molecule index in ASU are: ", molecule1_in_cell)

    translation_stats = []
    rotation_stats = []
    cell_length_a_stats = []
    cell_length_b_stats = []
    cell_length_c_stats = []
    cell_angle_alpha_stats = []
    cell_angle_beta_stats = []
    cell_angle_gamma_stats = []
    counter = 0
    atoms_input = atoms.copy()
    while (counter <= MC_stpes):
        if isinstance(perturbation_type, list):
            # random_number = random.choice([1,2,3,4,5,6,7,8])
            random_choices = get_random_choices(
                [f1, f2, f3, f4, f5, f6, f7, f8])
            random_number = random.choice(random_choices)
        else:
            random_number = perturbation_dict[perturbation_type]
        if random_number == 1:
            # translation
            atoms_input.set_calculator(calculator)
            ret_atoms, message = Monte_Carlo(atoms_input, calculator,
                                             space_group, f1, 'translate',
                                             counter, molecule1_in_cell,
                                             MC_stpes, args.debug)
            translation_stats.append(message)
            counter += 1
            atoms_input = ret_atoms.copy()
        elif random_number == 2:
            # rotation
            atoms_input.set_calculator(calculator)
            ret_atoms, message = Monte_Carlo(atoms_input, calculator,
                                             space_group, f2, 'rotation',
                                             counter, molecule1_in_cell,
                                             MC_stpes, args.debug)
            rotation_stats.append(message)
            counter += 1
            atoms_input = ret_atoms.copy()
        elif random_number == 3:
            # cell_length a
            atoms_input.set_calculator(calculator)
            ret_atoms, message = Monte_Carlo(atoms_input, calculator,
                                             space_group, f3, 'cell_length_a',
                                             counter, molecule1_in_cell,
                                             MC_stpes, args.debug)
            cell_length_a_stats.append(message)
            counter += 1
            atoms_input = ret_atoms.copy()
        elif random_number == 4:
            # cell_length b
            atoms_input.set_calculator(calculator)
            ret_atoms, message = Monte_Carlo(atoms_input, calculator,
                                             space_group, f4, 'cell_length_b',
                                             counter, molecule1_in_cell,
                                             MC_stpes, args.debug)
            cell_length_b_stats.append(message)
            counter += 1
            atoms_input = ret_atoms.copy()
        elif random_number == 5:
            # cell_length c
            atoms_input.set_calculator(calculator)
            ret_atoms, message = Monte_Carlo(atoms_input, calculator,
                                             space_group, f5, 'cell_length_c',
                                             counter, molecule1_in_cell,
                                             MC_stpes, args.debug)
            cell_length_c_stats.append(message)
            counter += 1
            atoms_input = ret_atoms.copy()
        elif random_number == 6:
            # cell_angle alpha
            atoms_input.set_calculator(calculator)
            ret_atoms, message = Monte_Carlo(atoms_input, calculator,
                                             space_group, f6,
                                             'cell_angle_alpha', counter,
                                             molecule1_in_cell, MC_stpes,
                                             args.debug)
            cell_angle_alpha_stats.append(message)
            counter += 1
            atoms_input = ret_atoms.copy()
        elif random_number == 7:
            # cell_angle beta
            atoms_input.set_calculator(calculator)
            ret_atoms, message = Monte_Carlo(atoms_input, calculator,
                                             space_group, f7,
                                             'cell_angle_beta', counter,
                                             molecule1_in_cell, MC_stpes,
                                             args.debug)
            cell_angle_beta_stats.append(message)
            counter += 1
            atoms_input = ret_atoms.copy()
        elif random_number == 8:
            # cell_angle gamma
            atoms_input.set_calculator(calculator)
            ret_atoms, message = Monte_Carlo(atoms_input, calculator,
                                             space_group, f8,
                                             'cell_angle_gamma', counter,
                                             molecule1_in_cell, MC_stpes,
                                             args.debug)
            cell_angle_gamma_stats.append(message)
            counter += 1
            atoms_input = ret_atoms.copy()
        #if counter % 1000 == 0:
        #    with open("MC_trace_%d.json"%counter, "w") as fh:
        #        json.dump(MC_trace, fh, indent=4)

    #with open("MC_trace.json", "w") as fh:
    #    json.dump(MC_trace, fh, indent=4)
    #print("MC trace are recorded in: MC_trace.json")

    if len(translation_stats):
        print("Acceptance ratio of translation move is %f" %
              (countX("Accepted", translation_stats) / len(translation_stats)))
    if len(rotation_stats):
        print("Acceptance ratio of rotation move is %f" %
              (countX("Accepted", rotation_stats) / len(rotation_stats)))
    if len(cell_length_a_stats):
        print("Acceptance ratio of cell length a move is %f" %
              (countX("Accepted", cell_length_a_stats) /
               len(cell_length_a_stats)))
    if len(cell_length_b_stats):
        print("Acceptance ratio of cell length b move is %f" %
              (countX("Accepted", cell_length_b_stats) /
               len(cell_length_b_stats)))
    if len(cell_length_c_stats):
        print("Acceptance ratio of cell length c move is %f" %
              (countX("Accepted", cell_length_c_stats) /
               len(cell_length_c_stats)))
    if len(cell_angle_alpha_stats):
        print("Acceptance ratio of cell angle alpha move is %f" %
              (countX("Accepted", cell_angle_alpha_stats) /
               len(cell_angle_alpha_stats)))
    if len(cell_angle_beta_stats):
        print("Acceptance ratio of cell angle beta move is %f" %
              (countX("Accepted", cell_angle_beta_stats) /
               len(cell_angle_beta_stats)))
    if len(cell_angle_gamma_stats):
        print("Acceptance ratio of cell angle gamma move is %f" %
              (countX("Accepted", cell_angle_gamma_stats) /
               len(cell_angle_gamma_stats)))
def Monte_Carlo(atoms,
                calculator,
                space_group,
                step_size,
                perturbation,
                counter,
                molecule1_in_cell=[],
                MC_steps=1000,
                debug=False):
    """
    A Monte_Carlo function that takes in an atoms instance and generate a new atoms instance base on metropolis monte carlo

    :type  atoms: Atoms.atoms
    :param atoms: ASE atoms instance which contains a collection of atoms and their related information

    :type  calculator: ase.calculator
    :param calculator: ANI calculator which is used to get force and energy base on atomic numbers and positions

    :type  space_group: ase.spacegroup.Spacegroup
    :param space_group: the space group that MC is performing under

    :type  step_size: array
    :param step_size: step size for T, R, cell_a, cell_b, cell_c, cell_alpha, cell_beta, cell_gamma

    :type  perturbation: str
    :param perturbation: the type of perturbation that MC is performing under

    :type  counter: int
    :param counter: the number of MC steps

    :type  molecule1_in_cell: array
    :param molecule1_in_cell: atom indexs for the asymmetric molecule in cell

    :type  MC_steps: int
    :param MC_steps: the number of MC steps that will be performed

    :type  debug: bool
    :param debug: show debug information including all accepted and rejected moves

    return a new frame base on metropolis monte carlo shown as below:

    if new_E < old_E:
        accepted, continue MD with new frame
    elif new_E > old_E:
        delta_Emn = new_E - old_E
        p = exp(-delta_Emn/kBT)
        generate a random number nu(0,1)
        if p > nu:
            accepted, continue MD with new frame
        else:
            rejected, continue MD with old frame
    """

    a, b, c, alpha, beta, gamma = atoms.get_cell_lengths_and_angles()
    xyz = atoms.get_positions()
    fraction = atoms.get_scaled_positions()
    #MC_trace[counter] = {}
    #MC_trace[counter]['a'] = a
    #MC_trace[counter]['b'] = b
    #MC_trace[counter]['c'] = c
    #MC_trace[counter]['alpha'] = alpha
    #MC_trace[counter]['beta'] = beta
    #MC_trace[counter]['gamma'] = gamma
    #MC_trace[counter]['xyz'] = xyz.tolist()
    #MC_trace[counter]['fraction'] = fraction.tolist()
    #MC_trace[counter]['density'] = len(atoms)/atoms.get_volume()

    old_atoms = atoms.copy()
    old_atoms.set_calculator(calculator)
    old_E = old_atoms.get_total_energy()
    #MC_trace[counter]['Energy'] = old_E

    try:
        if perturbation == "translate":
            new_atoms = generate_translate_frame(atoms, molecule1_in_cell,
                                                 space_group, step_size)
        elif perturbation == "rotation":
            new_atoms = generate_rotation_frame(atoms, molecule1_in_cell,
                                                space_group, step_size)
        elif perturbation == "cell_length_a":
            new_atoms = generate_cell_length_a_frame(atoms, molecule1_in_cell,
                                                     space_group, step_size)
        elif perturbation == "cell_length_b":
            new_atoms = generate_cell_length_b_frame(atoms, molecule1_in_cell,
                                                     space_group, step_size)
        elif perturbation == "cell_length_c":
            new_atoms = generate_cell_length_c_frame(atoms, molecule1_in_cell,
                                                     space_group, step_size)
        elif perturbation == "cell_angle_alpha":
            new_atoms = generate_cell_angle_alpha_frame(
                atoms, molecule1_in_cell, space_group, step_size)
        elif perturbation == "cell_angle_beta":
            new_atoms = generate_cell_angle_beta_frame(atoms,
                                                       molecule1_in_cell,
                                                       space_group, step_size)
        elif perturbation == "cell_angle_gamma":
            new_atoms = generate_cell_angle_gamma_frame(
                atoms, molecule1_in_cell, space_group, step_size)

        if (len(molecule_lists(new_atoms)) != len(molecule_lists(old_atoms))):
            print("%s move by %f to Frame %d Rejected due to clash!" %
                  (perturbation, step_size, counter))
            outfile = "Rejected_clash_%d.cif" % counter
            ase_io.write(outfile, new_atoms)
            return old_atoms, "Rejected"
    except:
        print("failed during generation of frame %d by doing %s change" %
              (counter, perturbation))
        outfile = "Failed_frame_%d.cif" % counter
        ase_io.write(outfile, old_atoms)
        return old_atoms, "Rejected"

    new_atoms.set_calculator(calculator)
    new_E = new_atoms.get_total_energy()

    if new_E < old_E:
        print("Frame %d Accepted!" % counter)
        if counter % 100 == 0 or MC_steps - counter < 100 or debug:
            outfile = "Accepted_%d.cif" % counter
            ase_io.write(outfile, new_atoms)
        return new_atoms, "Accepted"
    else:
        delta_Emn = new_E - old_E
        delta_Emn = delta_Emn * 23  # ev to kcal/mol
        p = math.exp(-delta_Emn / units.kB / 300)
        nu = random.uniform(0, 1)
        if p > nu:
            print("Frame %d Accepted!" % counter)
            if counter % 100 == 0 or MC_steps - counter < 100 or debug:
                outfile = "Accepted_%d.cif" % counter
                ase_io.write(outfile, new_atoms)
            return new_atoms, "Accepted"
        else:
            print("Frame %d Rejected!" % counter)
            return old_atoms, "Rejected"
def main():

    args = parse_args()
    print("args", args)

    if args.implementation == TORCHANI:
        from torchani_calculator import torchani_calculator
        calculator = torchani_calculator(args.network_type)
    elif args.implementation == AES_ANI:
        from ani_ase import ani_ase_calculator
        calculator = ani_ase_calculator(args.network_type)
    elif args.implementation == KHAN:
        from khan_calculator import khan_calculator
        calculator = khan_calculator(args.network_type, args.khan_network,
                                     args.numb_networks)

    assert args.cif_file.endswith('.cif')

    print('debug? ', args.debug)
    atoms = ase_io.read(args.cif_file)
    numb_molecules = len(molecule_lists(atoms))
    print('number of molecules: ', numb_molecules)
    MC_stpes = args.MC
    space_group = Spacegroup(args.space_group)
    # step size in MC
    f1, f2, f3, f4, f5, f6, f7, f8 = args.MC_f1_f2_f3_f4_f5_f6_f7_f8
    perturbation_type = args.perturbation_type
    molecule1_in_cell = []
    for i in range(1, atoms.get_number_of_atoms()):
        if atom_belong_to_mol1(i, atoms):
            molecule1_in_cell.append(i)
    print("initial unit cell")
    print(atoms.cell)
    print("To do Monte Carlo for %d step." % MC_stpes)
    print("Molecule index in ASU are: ", molecule1_in_cell)

    counter = 0
    atoms.set_calculator(calculator)
    while (counter <= MC_stpes):
        if isinstance(perturbation_type, list):
            # random_number = random.choice([1,2,3,4,5,6,7,8])
            random_choices = get_random_choices(
                [f1, f2, f3, f4, f5, f6, f7, f8])
            random_number = random.choice(random_choices)
        else:
            random_number = perturbation_dict[perturbation_type]
        if random_number == 1:
            # translation
            Monte_Carlo(atoms, calculator, space_group, f1, 'translate',
                        counter, numb_molecules, molecule1_in_cell, MC_stpes,
                        args.debug)
            counter += 1
        elif random_number == 2:
            # rotation
            Monte_Carlo(atoms, calculator, space_group, f2, 'rotation',
                        counter, numb_molecules, molecule1_in_cell, MC_stpes,
                        args.debug)
            counter += 1
        elif random_number == 3:
            # cell_length a
            Monte_Carlo(atoms, calculator, space_group, f3, 'cell_length_a',
                        counter, numb_molecules, molecule1_in_cell, MC_stpes,
                        args.debug)
            counter += 1
        elif random_number == 4:
            # cell_length b
            Monte_Carlo(atoms, calculator, space_group, f4, 'cell_length_b',
                        counter, numb_molecules, molecule1_in_cell, MC_stpes,
                        args.debug)
            counter += 1
        elif random_number == 5:
            # cell_length c
            Monte_Carlo(atoms, calculator, space_group, f5, 'cell_length_c',
                        counter, numb_molecules, molecule1_in_cell, MC_stpes,
                        args.debug)
            counter += 1
        elif random_number == 6:
            # cell_angle alpha
            Monte_Carlo(atoms, calculator, space_group, f6, 'cell_angle_alpha',
                        counter, numb_molecules, molecule1_in_cell, MC_stpes,
                        args.debug)
            counter += 1
        elif random_number == 7:
            # cell_angle beta
            Monte_Carlo(atoms, calculator, space_group, f7, 'cell_angle_beta',
                        counter, numb_molecules, molecule1_in_cell, MC_stpes,
                        args.debug)
            counter += 1
        elif random_number == 8:
            # cell_angle gamma
            Monte_Carlo(atoms, calculator, space_group, f8, 'cell_angle_gamma',
                        counter, numb_molecules, molecule1_in_cell, MC_stpes,
                        args.debug)
            counter += 1
Esempio n. 15
0
def main():

    args = parse_args()
    print("args", args)

    if args.implementation == TORCHANI:
        from torchani_calculator import torchani_calculator
        calculator = torchani_calculator(args.network_type)
    elif args.implementation == AES_ANI:
        from ani_ase import ani_ase_calculator
        calculator = ani_ase_calculator(args.network_type)
    elif args.implementation == KHAN:
        from khan_calculator import khan_calculator
        calculator = khan_calculator(args.network_type, args.khan_network,
                                     args.numb_networks)

    assert args.cif_file.endswith('.cif')

    print('debug? ', args.debug)
    atoms = ase_io.read(args.cif_file)
    numb_molecules = len(molecule_lists(atoms))
    print('number of molecules: ', numb_molecules)
    total_number_of_molecules = numb_molecules
    MC_stpes = args.MC
    space_group = Spacegroup(args.space_group)
    # step size in MC
    f1, f2, f3, f4 = args.MC_f1_f2_f3_f4
    perturbation_type = args.perturbation_type
    molecule1_in_cell = []
    for i in range(1, atoms.get_number_of_atoms()):
        if atom_belong_to_mol1(i, atoms):
            molecule1_in_cell.append(i)
    # print("Space group of crystal: %s" % spacegroup.get_spacegroup(atoms))
    print("initial unit cell")
    print(atoms.cell)
    print("To do Monte Carlo for %d step." % MC_stpes)
    print("Molecule index in ASU are: ", molecule1_in_cell)

    translation_stats = []
    rotation_stats = []
    cell_length_stats = []
    cell_angle_stats = []
    counter = 0
    atoms_input = atoms.copy()
    # space_group = spacegroup.get_spacegroup(atoms)
    while (counter <= MC_stpes):
        if isinstance(perturbation_type, list):
            random_number = random.choice([1, 2, 3, 4])
        else:
            random_number = perturbation_dict[perturbation_type]
        if random_number == 1:
            # translation
            atoms_input.set_calculator(calculator)
            ret_atoms, message = Monte_Carlo(atoms_input, calculator,
                                             space_group, f1, 'translate',
                                             counter, molecule1_in_cell,
                                             MC_stpes, args.debug)
            translation_stats.append(message)
            counter += 1
            atoms_input = ret_atoms.copy()
        elif random_number == 2:
            # rotation
            atoms_input.set_calculator(calculator)
            ret_atoms, message = Monte_Carlo(atoms_input, calculator,
                                             space_group, f2, 'rotation',
                                             counter, molecule1_in_cell,
                                             MC_stpes, args.debug)
            rotation_stats.append(message)
            counter += 1
            atoms_input = ret_atoms.copy()
        elif random_number == 3:
            # cell_length
            atoms_input.set_calculator(calculator)
            ret_atoms, message = Monte_Carlo(atoms_input, calculator,
                                             space_group, f3, 'cell_length',
                                             counter, molecule1_in_cell,
                                             MC_stpes, args.debug)
            cell_length_stats.append(message)
            counter += 1
            atoms_input = ret_atoms.copy()
        else:
            # cell_angle
            atoms_input.set_calculator(calculator)
            ret_atoms, message = Monte_Carlo(atoms_input, calculator,
                                             space_group, f4, 'cell_angle',
                                             counter, molecule1_in_cell,
                                             MC_stpes, args.debug)
            cell_angle_stats.append(message)
            counter += 1
            atoms_input = ret_atoms.copy()

    with open("MC_trace.json", "w") as fh:
        json.dump(MC_trace, fh, indent=4)
    print("MC trace are recorded in: MC_trace.json")

    print("Acceptance ratio of translation move is %f" %
          (countX("Accepted", translation_stats) / len(translation_stats)))
    print("Acceptance ratio of rotation move is %f" %
          (countX("Accepted", rotation_stats) / len(rotation_stats)))
    print("Acceptance ratio of cell length move is %f" %
          (countX("Accepted", cell_length_stats) / len(cell_length_stats)))
    print("Acceptance ratio of cell angle move is %f" %
          (countX("Accepted", cell_angle_stats) / len(cell_angle_stats)))
def change_cell_length(atoms, space_group):

    print(atoms.get_atomic_numbers())
    name = get_name(atoms.get_atomic_numbers())
    print(name)
    # to do
    molecule1, molecule2, molecule3, molecule4 = molecule_lists(
        atoms)[0], molecule_lists(atoms)[1], molecule_lists(
            atoms)[2], molecule_lists(atoms)[3]  # [1,5,9,13,17,21,etc]

    print(molecule1)
    print(molecule2)
    print(molecule3)
    print(molecule4)
    scaled_positions = atoms.get_scaled_positions()
    #print("scaled_positions: ", scaled_positions)
    molecule1_scaled_positions = np.array(
        [scaled_positions[i] for i in molecule1])
    cell_params = atoms.get_cell()
    #print(cell_params)
    #print(atoms.get_positions())
    a_vector, b_vector, c_vector = cell_params[0], cell_params[1], cell_params[
        2]
    molecule1_vectors = np.array([
        faction[0] * a_vector + faction[1] * b_vector + faction[2] * c_vector
        for faction in molecule1_scaled_positions
    ])
    new_atoms = atoms.copy()
    new_atoms.set_cell(cell_params +
                       np.array([[1, 0, 0], [0, 1, 0], [0.1, 0, 1]]),
                       scale_atoms=False)
    new_cell_params = new_atoms.get_cell()
    print("new_cell_params: ", new_cell_params)
    new_a_vector, new_b_vector, new_c_vector = new_cell_params[
        0], new_cell_params[1], new_cell_params[2]
    new_vectors = []
    for v in molecule1_vectors:
        Va = np.dot(
            np.cross(new_b_vector, new_c_vector) /
            np.dot(new_a_vector, np.cross(new_b_vector, new_c_vector)), v)
        Vb = np.dot(
            np.cross(new_c_vector, new_a_vector) /
            np.dot(new_b_vector, np.cross(new_c_vector, new_a_vector)), v)
        Vc = np.dot(
            np.cross(new_a_vector, new_b_vector) /
            np.dot(new_c_vector, np.cross(new_a_vector, new_b_vector)), v)
        new_vectors.append([Va, Vb, Vc])
    new_sclaed_positions = np.array(new_vectors)
    print("get_symop(): ", space_group.get_symop())

    sites = []
    for kind, pos in enumerate(new_sclaed_positions):
        for rot, trans in space_group.get_symop():
            site = np.dot(rot, pos) + trans
            sites.append(site)
    print(np.array(sites))
    new_positions = np.array([
        faction[0] * new_a_vector + faction[1] * new_b_vector +
        faction[2] * new_c_vector for faction in sites
    ])
    print(new_positions)

    #wire = Atoms('',
    #         positions=[[0, L / 2, L / 2]],
    #         cell=[d, L, L],
    #         pbc=[1, 0, 0])
    writer = Atoms(name,
                   positions=new_positions,
                   cell=new_atoms.get_cell(),
                   pbc=[1, 1, 1])

    #final_scaled_positions = get_equivalent_sites(new_sclaed_positions, space_group)
    #print("final_scaled_positions: ", final_scaled_positions)

    #new_atoms.set_scaled_positions(final_scaled_positions)

    for i in molecule1:
        print(
            writer.get_distances(i, molecule1) -
            atoms.get_distances(i, molecule1))
    #print(atoms.get_distance(24,36, mic=False, vector=True))
    #print(new_atoms.get_distance(24,36, mic=False, vector=True))
    print(writer.get_cell())

    return writer
    ret_atoms_translate = generate_translate_frame(ret_atoms_rotation,
                                                   molecule1_atoms_index,
                                                   space_group, 2.0)
    print("after translation ", molecule_lists(ret_atoms_translate))
    ret_atoms = ret_atoms_translate.copy()

    return ret_atoms


if __name__ == "__main__":

    print("runing main function for debugging...")
    atoms = ase_io.read(sys.argv[1])
    spacegroup_number = sys.argv[2]
    molecule1_atoms_index = molecule_lists(atoms)[0]
    print(molecule_lists(atoms))
    print("molecule1_atoms_index: ", molecule1_atoms_index)
    if spacegroup_number:
        space_group = Spacegroup(int(spacegroup_number))
    else:
        space_group = spacegroup.get_spacegroup(atoms)
    print("before perturbation: ", space_group)

    # HY this is tests for perturb functions.
    #generate_translate_frame(atoms, molecule1_atoms_index, space_group, 0.05)
    #generate_rotation_frame(atoms, molecule1_atoms_index, space_group, 0.05)
    #generate_cell_length_a_frame(atoms, molecule1_atoms_index, space_group, 10.0)
    #generate_cell_length_b_frame(atoms, molecule1_atoms_index, space_group, 10.0)
    #generate_cell_length_c_frame(atoms, molecule1_atoms_index, space_group, 1.0)
    generate_cell_angle_beta_frame(atoms, molecule1_atoms_index, space_group,