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)
def reshape(mof, rotation, initial_coordinate): """ Apply rotation and translation operations to given MOF - rotation = [x_angle, y_angle, z_angle] in degrees - initial_coordinate = [x, y, z] in cartesian coordinates """ first_point = initial_coordinate x_angle, y_angle, z_angle = [math.radians(a) for a in rotation] structure = {'atom_names': [], 'atom_coors': [], 'name': mof.name} rot_coor = mof.packed_coors[0][0] translation_vector = sub3(first_point, rot_coor) for unit_cell in mof.packed_coors: for atom_coor in unit_cell: rot_coor = atom_coor rot_coor = xyz_rotation(rot_coor, [x_angle, y_angle, z_angle]) new_coor = add3(rot_coor, translation_vector) structure['atom_coors'].append(new_coor) structure['atom_names'] = len(mof.packed_coors) * mof.atom_names return structure
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