示例#1
0
def initial_coordinates(mof, energy_map, atom_list, energy_limit):
    """
    Determine initial coordinates to start interpenetration simulations from.
    Points are determined acoording to their energy (accepted if energy < energy_limit)
    and their position (accepted if applying pbc does not change its coordinates)
    """
    reference_atom = 'C'
    if reference_atom in atom_list['atom']:
        ref_atom_index = int(atom_list['atom'].index(reference_atom) + 3)
    else:
        ref_atom_index = 3
    initial_coors = []
    energy_count = 0
    pbc_count = 0

    for emap_line in energy_map:
        emap_coor = [emap_line[0], emap_line[1], emap_line[2]]
        pbc_coor = pbc3(emap_coor, mof.to_frac, mof.to_car)
        pbc_x = round(pbc_coor[0], 1)
        pbc_y = round(pbc_coor[1], 1)
        pbc_z = round(pbc_coor[2], 1)
        if pbc_x == emap_coor[0] and pbc_y == emap_coor[1] and pbc_z == emap_coor[2]:
            if emap_line[ref_atom_index] < energy_limit:
                initial_coors.append([emap_line[0], emap_line[1], emap_line[2]])
            else:
                energy_count += 1
        else:
            pbc_count += 1

    # print('Ommited PBC: ', pbc_count, ' Energy: ', energy_count)
    return initial_coors
示例#2
0
def check_extension(sim_par, base_mof, mobile_mof, emap, emap_atom_list, new_structure):
    """
    Checks collision between interpenetrating layer and base layer for a determined distance.
    Distance is calculated from given ext_cut_off value which determines the packing amount of the
    interpenetrating layer.
    Each coordinate in the interpenetrating layer is checked for high energy values by applying
    perodic boundary conditions to the coordinate according to energy map of the base layer.
    """
    emap_max = [emap[-1][0], emap[-1][1], emap[-1][2]]
    emap_min = [emap[0][0], emap[0][1], emap[0][2]]
    side_length = [emap_max[0] - emap_min[0] + 1, emap_max[1] - emap_min[1] + 1, emap_max[2] - emap_min[2] + 1]
    x_length, y_length = int(side_length[1] * side_length[2]), int(side_length[2])

    energy_limit = sim_par['atom_energy_limit']
    ext_cut_off = sim_par['ext_cut_off']
    rotation_info = new_structure['rotation']
    first_point = new_structure['first_point']
    translation_vector = new_structure['translation_vector']

    packing_factor = Packing.factor(mobile_mof.uc_size, ext_cut_off)
    uc_vectors = Packing.uc_vectors(mobile_mof.uc_size, mobile_mof.uc_angle)
    trans_vec = Packing.translation_vectors(packing_factor, uc_vectors)
    packed_coors = Packing.uc_coors(trans_vec, packing_factor, uc_vectors, mobile_mof.atom_coors)

    x_angle, y_angle, z_angle = rotation_info
    collision = False
    collision_info = {'exist': collision, 'coor': None, 'pbc_coor': None}

    for unit_cell in packed_coors:

        if not collision:

            for coor_index, coor in enumerate(unit_cell):

                if not collision:

                    rot_coor = coor
                    rot_coor = xyz_rotation(rot_coor, [x_angle, y_angle, z_angle])
                    new_coor = add3(rot_coor, translation_vector)
                    pbc_coor = pbc3(new_coor, base_mof.to_frac, base_mof.to_car)
                    atom_name = mobile_mof.atom_names[coor_index]
                    atom_index = energy_map_atom_index(atom_name, emap_atom_list)
                    point_energy = tripolate(pbc_coor, atom_index, emap, x_length, y_length)

                    if point_energy < energy_limit:
                        continue
                    else:
                        collision = True
                        collision_info = {'exist': collision,
                                          'coor': [float(round(p, 3)) for p in new_coor],
                                          'pbc_coor': [float(round(p, 3)) for p in pbc_coor]}
                        break
                else:
                    break
        else:
            break

    return collision_info
示例#3
0
def regenerate(s1_name, s2_name, rotation, initial_coordinate, sim_par, sim_dir, export_dir, colorify=True, index=1, format='cif'):
    """
    Reconstruct interpenetrated structure for given MOFs with rotation and initial coordinate.
    """
    s1_mof = MOF(os.path.join(sim_dir['mof_dir'], s1_name + '.cif'))
    s2_mof = MOF(os.path.join(sim_dir['mof_dir'], s2_name + '.cif'))
    s2_mof_length = len(s2_mof)
    first_point = initial_coordinate
    x_angle, y_angle, z_angle = [math.radians(a) for a in rotation]
    structure = {'atom_names': [], 'atom_coors': [], 'pbc_coors': []}

    for idx in range(s2_mof_length):
        if idx == 0:
            atom_name = s2_mof.atom_names[idx]
            rot_coor = s2_mof.atom_coors[idx]
            rot_coor = xyz_rotation(rot_coor, [x_angle, y_angle, z_angle])
            translation_vector = sub3(first_point, rot_coor)
        else:
            atom_name = s2_mof.atom_names[idx]
            rot_coor = s2_mof.atom_coors[idx]
            rot_coor = xyz_rotation(rot_coor, [x_angle, y_angle, z_angle])
            new_coor = add3(rot_coor, translation_vector)
            pbc_coor = pbc3(new_coor, s1_mof.to_frac, s1_mof.to_car)

            structure['atom_coors'].append(new_coor)
            structure['pbc_coors'].append(pbc_coor)
            structure['atom_names'].append(atom_name)

    new_structure = {'atom_names': structure['atom_names'], 'name': s2_mof.name}
    if sim_par['export_pbc']:
        new_structure['atom_coors'] = structure['pbc_coors']
    else:
        new_structure['atom_coors'] = structure['atom_coors']

    # Export structure file
    new_s2_mof = MOF(new_structure, file_format='dict')
    joined_mof = s1_mof.join(new_s2_mof, colorify=False)
    joined_mof.name += '_' + str(index)
    joined_mof.export(export_dir, file_format=format)

    if colorify:
        new_s2_mof = MOF(new_structure, file_format='dict')
        joined_mof_color = s1_mof.join(new_s2_mof, colorify=True)
        joined_mof_color.name += '_' + str(index) + 'C'
        joined_mof_color.export(export_dir, file_format=format)
示例#4
0
def check_interpenetration(sim_par, base_mof, mobile_mof, emap, atom_list):
    """
    Run interpenetration algorithm with given simulation parameters and energy map.
    Returns simulation summary and structural information on the discovered structures.
    """
    # Initialize simulation parameters
    structure_energy_limit = sim_par['structure_energy_limit']
    atom_energy_limit = sim_par['atom_energy_limit']
    # atom_energy_limit = sim_par['energy_density_limit'] * mobile_mof.ucv
    energy_density_limit = sim_par['energy_density_limit']
    rotation_freedom = sim_par['rotation_freedom']
    summary_percent = sim_par['summary_percent']
    try_all_rotations = sim_par['try_all_rotations']
    # Get energy map dimensions for trilinear interpolation
    emap_max = [emap[-1][0], emap[-1][1], emap[-1][2]]
    emap_min = [emap[0][0], emap[0][1], emap[0][2]]
    side_length = [emap_max[0] - emap_min[0] + 1, emap_max[1] - emap_min[1] + 1, emap_max[2] - emap_min[2] + 1]
    x_length, y_length = int(side_length[1] * side_length[2]), int(side_length[2])

    if try_all_rotations:
        all_rot_degrees = possible_rotations(sim_par['rotation_freedom'])
        rotation_limit = len(all_rot_degrees)
        sim_par['rotation_limit'] = rotation_limit
    else:
        rotation_limit = sim_par['rotation_limit']

    initial_coors = initial_coordinates(base_mof, emap, atom_list, atom_energy_limit)
    trial_limit = len(initial_coors) * rotation_limit
    div = round(trial_limit / (100 / summary_percent))
    rot_freedom = 360 / rotation_freedom
    # omitted_coordinates = len(emap) - len(initial_coors)

    summary = {'percent': [], 'structure_count': [], 'trial_count': []}
    new_structures = []
    abort_ip = False
    mobile_mof_length = len(mobile_mof)
    structure_count = 0
    structure_total_energy = 0
    ucv = mobile_mof.ucv
    energy_density = 0
    initial_coor_index = 0
    rotation_index = 0

    # Interpenetration trial loop for different positions and orientations
    for t in range(trial_limit):
        abort_ip = False
        # Interpenetration trial loop for a specific position and different orientations
        for idx in range(mobile_mof_length):

            if not abort_ip:
                # If the interpenetration is just starting select rotation angles
                if idx == 0:
                    # Determine random angles for rotation in 3D space

                    # Determine first point for interpenetrating structure
                    if t % rotation_limit == 0:
                        # Start with original orientation for first trial
                        x_angle, y_angle, z_angle = [0, 0, 0]
                        first_point = initial_coors[initial_coor_index]
                        initial_coor_index += 1
                        rotation_index = 0
                    elif try_all_rotations:
                        x_angle, y_angle, z_angle = all_rot_degrees[rotation_index]
                    else:
                        x_angle = 2 * math.pi * math.floor(random() * rot_freedom) / rot_freedom
                        y_angle = 2 * math.pi * math.floor(random() * rot_freedom) / rot_freedom
                        z_angle = 2 * math.pi * math.floor(random() * rot_freedom) / rot_freedom

                    rotation_index += 1
                    # Rotate first atom of the mobile MOF
                    atom_name = mobile_mof.atom_names[idx]
                    rot_coor = mobile_mof.atom_coors[idx]
                    rot_coor = xyz_rotation(rot_coor, [x_angle, y_angle, z_angle])
                    translation_vector = sub3(first_point, rot_coor)

                    # Initialize new structure dictionary
                    structure = {'atom_names': [], 'atom_coors': [], 'pbc_coors': []}
                    structure['first_point'] = first_point
                    structure['translation_vector'] = translation_vector
                    structure['atom_coors'].append(first_point)
                    structure['pbc_coors'].append(first_point)
                    structure['atom_names'].append(atom_name)
                    structure['rotation'] = [x_angle, y_angle, z_angle]

                # If interpenetration is still going on
                elif idx < mobile_mof_length - 1:
                    atom_name = mobile_mof.atom_names[idx]
                    rot_coor = mobile_mof.atom_coors[idx]
                    rot_coor = xyz_rotation(rot_coor, [x_angle, y_angle, z_angle])
                    new_coor = add3(rot_coor, translation_vector)
                    pbc_coor = pbc3(new_coor, base_mof.to_frac, base_mof.to_car)

                    emap_atom_index = energy_map_atom_index(atom_name, atom_list)
                    point_energy = tripolate(pbc_coor, emap_atom_index, emap, x_length, y_length)
                    structure_total_energy += point_energy
                    energy_density += point_energy / ucv

                    if energy_density > energy_density_limit:
                        structure_total_energy = 0
                        energy_density = 0
                        abort_ip = True
                        break  # Fix this part (break interpenetration trial loop)
                    else:
                        structure['atom_coors'].append(new_coor)
                        structure['pbc_coors'].append(pbc_coor)
                        structure['atom_names'].append(atom_name)

                # If interpenetration trial ended with no collision - record structure info
                else:
                    structure['energy'] = structure_total_energy
                    structure['energy_density'] = energy_density
                    new_structures.append(structure)
                    structure_count += 1
                    structure_total_energy = 0
                    energy_density = 0

        # Record simulation progress according to division (div) and summary
        if t % div == 0:
            percent_complete = round(t / trial_limit * 100)
            summary['percent'].append(percent_complete)
            summary['structure_count'].append(structure_count)
            summary['trial_count'].append(t)

    return summary, new_structures