def setUp(self): pymagen_sodium = Molecule(species=['Na'], coords=[[999.0, 999.0, 999.0]], charge=1) # noinspection PyProtectedMember sodium_obmol = BabelMolAdaptor(pymagen_sodium)._obmol acetoxyq_anion_qcout = QcOutput( os.path.join(test_dir, "acetoxyq_anion.out")) pymatgen_acetoxyq = acetoxyq_anion_qcout.data[0]["molecules"][-1] acetoxyq_obmol = BabelMolAdaptor(pymatgen_acetoxyq)._obmol tfsi_qcout = QcOutput(os.path.join(test_dir, "tfsi.qcout")) pymatgen_tfsi = tfsi_qcout.data[0]["molecules"][-1] # noinspection PyProtectedMember tfsi_obmol = BabelMolAdaptor(pymatgen_tfsi)._obmol fragments = [sodium_obmol, tfsi_obmol] nums_fragments = [1, 1] self.acetoxyq_natfsi_placer = IonPlacer(acetoxyq_obmol, fragments, nums_fragments, None) rad_util = AtomicRadiusUtils(covalent_radius_scale=3.0, metal_radius_scale=1.5) mol_radius = rad_util.get_radius(acetoxyq_obmol) cation_radius = rad_util.get_radius(sodium_obmol) anion_radius = rad_util.get_radius(tfsi_obmol) mol_coords = IonPlacer.normalize_molecule(acetoxyq_obmol) fragments_atom_radius = [cation_radius, anion_radius] nums_fragments = [1, 1] self.detector = ContactDetector(mol_coords, mol_radius, fragments_atom_radius, nums_fragments)
def taboo_current_position(self, raw_position_only=False): self.tabooed_raw_positions.append( list(itertools.chain(*self.current_raw_position))) if not raw_position_only: if self.current_optimized_position is None: mol = self._get_super_molecule(self.current_raw_position) #energy, final_mol = self.run_mopac(mol) #energy, final_mol = self.run_xtb(mol) #energy = self.run_xtb(mol) final_mol = BabelMolAdaptor(mol)._obmol from rubicon.utils.ion_arranger.ion_arranger import IonPlacer final_coords = IonPlacer.normalize_molecule(final_mol) self.current_optimized_position = final_coords self.tabooed_optimizated_positions.append( self.current_optimized_position) # taboo is called from ion arranger self.save_current_best_position() self.memory_positions = [] self.best_energy = None self.current_best_optimized_position = None self.current_best_raw_position = None self.best_mol = None self.best_run_number = None del self.sqm_umbrella_centers[:]
def from_qchem_output(cls, mol_qcout, cation_qcout, anion_qcout, covalent_radius_scale=2.0, metal_radius_scale=0.5): from rubicon.utils.ion_arranger.ion_arranger import IonPlacer mol_charges = mol_qcout.data[0]["charges"]["chelpg"] cation_charges = cation_qcout.data[0]["charges"]["chelpg"] anion_charges = anion_qcout.data[0]["charges"]["chelpg"] pymatgen_mol_molecule = mol_qcout.data[0]["molecules"][-1] pymatgen_mol_cation = cation_qcout.data[0]["molecules"][-1] pymatgen_mol_anion = anion_qcout.data[0]["molecules"][-1] obmol_mol = BabelMolAdaptor(pymatgen_mol_molecule)._obmol obmol_cation = BabelMolAdaptor(pymatgen_mol_cation)._obmol obmol_anion = BabelMolAdaptor(pymatgen_mol_anion)._obmol mol_coords = IonPlacer.normalize_molecule(obmol_mol) rad_util = AtomicRadiusUtils(covalent_radius_scale, metal_radius_scale) mol_radius = rad_util.get_radius(obmol_mol) cation_radius = rad_util.get_radius(obmol_cation) anion_radius = rad_util.get_radius(obmol_anion) evaluator = HardSphereElectrostaticEnergyEvaluator( mol_coords, mol_radius, cation_radius, anion_radius, mol_charges, cation_charges, anion_charges) return evaluator
def _construct_largest_cap_energy_evaluator(covalent_radius_scale, metal_radius_scale, mol_coords, ob_mol, ob_fragments, nums_fragments, bound_setter="chain"): rad_util = AtomicRadiusUtils(covalent_radius_scale, metal_radius_scale) mol_radius = rad_util.get_radius(ob_mol) fragments_atom_radius = [ rad_util.get_radius(frag) for frag in ob_fragments ] from rubicon.utils.ion_arranger.ion_arranger import IonPlacer bounder = IonPlacer.get_bounder(mol_coords, ob_fragments, nums_fragments, bound_setter) max_cap = max( bounder.upper_bound) * 2.0 / AtomicRadiusUtils.angstrom2au evaluator = LargestContactGapEnergyEvaluator(mol_coords, mol_radius, fragments_atom_radius, nums_fragments, max_cap, threshold=0.01) return evaluator
def __init__(self, ob_mol, ob_fragments, nums_fragments, total_charge, lower_covalent_radius_scale=2.0, lower_metal_radius_scale=0.8, upper_covalent_radius_scale=3.0, upper_metal_radius_scale=1.5, taboo_tolerance_ang=1.0, force_order_fragment=False, bound_setter="chain", solvent=None): """ Args: ob_mol: ob_fragments: nums_fragments: total_charge: solvent: Any implicit solvent supported by the xtb ALPB model. See https://xtb-docs.readthedocs.io/en/latest/gbsa.html """ from rubicon.utils.ion_arranger.ion_arranger import IonPlacer self.mol_coords = IonPlacer.normalize_molecule(ob_mol) super(SemiEmpricalQuatumMechanicalEnergyEvaluator, self).__init__(self.mol_coords) self.total_charge = total_charge self.force_ordered_fragment = force_order_fragment self.lower_sphere = self._construct_hardsphere_energy_evaluator( lower_covalent_radius_scale, lower_metal_radius_scale, self.mol_coords, ob_mol, ob_fragments, nums_fragments) self.contact_detector = self._construct_contact_detector( upper_covalent_radius_scale, upper_metal_radius_scale, self.mol_coords, ob_mol, ob_fragments, nums_fragments) self.layout_order = OrderredLayoutEnergyEvaluator( self.mol_coords, nums_fragments) grav = "rmsd_gap" if grav == "rmsd_gap": self.gravitation = self._construct_contact_cap_rmsd_energy_evaluator( upper_covalent_radius_scale, upper_metal_radius_scale, self.mol_coords, ob_mol, ob_fragments, nums_fragments) elif grav == "largest_gap": self.gravitation = self._construct_largest_cap_energy_evaluator( upper_covalent_radius_scale, upper_metal_radius_scale, self.mol_coords, ob_mol, ob_fragments, nums_fragments, bound_setter=bound_setter) self.mol_species = IonPlacer.get_mol_species(ob_mol) self.fragments_species = [ IonPlacer.get_mol_species(frag) for frag in ob_fragments ] self.ob_fragments = ob_fragments self.nums_fragments = nums_fragments self.run_number = 1 self.global_best_energy = 0.0 self.memory_position_tolerance_au = 0.3 * AtomicRadiusUtils.angstrom2au self.memory_positions = [] self.memory_size = 1000 self.current_raw_position = None self.current_optimized_position = None self.taboo_tolerance_au = taboo_tolerance_ang * AtomicRadiusUtils.angstrom2au self.tabooed_raw_positions = [] self.tabooed_optimizated_positions = [] self.current_best_raw_position = None self.current_best_optimized_position = None self.best_umbrella_ratio = 3.0 self.best_energy = None self.best_mol = None self.best_run_number = None self.sqm_umbrella_centers = [] self.sqm_umbrella = UmbrellarForceEnergyEvaluator( self.mol_coords, self.sqm_umbrella_centers, self.taboo_tolerance_au, self.best_umbrella_ratio) self.gap_umbrella_centers = [] self.gap_umbrella = None self.smallest_gap = 9999999999.9 self.arranger = None self.solvent = solvent
def calc_energy(self, fragments_coords): # Energy orders: # Tabooed(1.0E5) > Umbrella(7.0E4) > Layout (6.0E4) > HardSphere (5.0E4) > # gravity (4.0E4) > PM7 (-1.0E1) tabooed_energy = 1.0E5 self.current_raw_position = fragments_coords self.current_optimized_position = None if self.is_current_position_tabooed(position_type="raw"): # 100000 return tabooed_energy # if self.gap_umbrella is not None: # gap_umbrella_energy = self.gap_umbrella.calc_energy( # fragments_coords) # if gap_umbrella_energy > self.gap_umbrella.base_energy - 100.0: # # 70000 # print('gap_umbrella') # return gap_umbrella_energy # sqm_umbrella_energy = self.sqm_umbrella.calc_energy(fragments_coords) # if sqm_umbrella_energy > self.sqm_umbrella.base_energy - 100.0: # print('sqm_umbrella') # return sqm_umbrella_energy # if self.force_ordered_fragment: # energy = self.layout_order.calc_energy(fragments_coords) # if energy > self.layout_order.base_energy - 100.0: # print('force_ordered_fragment') # return energy # energy = self.lower_sphere.calc_energy(fragments_coords) # if energy > self.lower_sphere.base_energy - 100.0: # print('lower_sphere') # return energy # if not self.contact_detector.is_contact(fragments_coords): # energy = self.gravitation.calc_energy(fragments_coords) # if energy > self.gravitation.base_energy - 100.0: # self.build_or_extend_gap_umbrella( # current_gap=energy - self.gravitation.base_energy, # fragments_coords=fragments_coords) # print('gravitation') # return energy memorized_energy = self.query_memory_positions(fragments_coords) if memorized_energy is not None: energy = memorized_energy elif self.contact_detector.is_contact(fragments_coords): print('Contact!') self.taboo_current_position(raw_position_only=True) return 1e5 else: mol = self._get_super_molecule(fragments_coords) # energy, final_mol = self.run_mopac(mol) try: # energy = self.run_xtb(mol) energy, final_mol = self.run_xtb(mol) final_mol = BabelMolAdaptor(final_mol)._obmol except ValueError as e: print(e) self.taboo_current_position(raw_position_only=True) return 1e5 if energy < self.global_best_energy: print(f'New global best energy {energy} found') self.global_best_energy = energy # shutil.copy("xtbopt.xyz", os.path.join(cur_dir, "best_mol.xyz")) from rubicon.utils.ion_arranger.ion_arranger import IonPlacer final_coords = IonPlacer.normalize_molecule(final_mol) self.current_optimized_position = final_coords if self.is_current_position_tabooed(position_type="optimized"): self.taboo_current_position(raw_position_only=True) print("Position is tabooed. Aborting.") return tabooed_energy # energy = round(energy, 5) # if self.is_optimized_position_inside_the_best_promixity( # final_coords): # print('position is inside proxmity') if self.best_energy is None or energy < self.best_energy or self.current_best_optimized_position is None: self.best_energy = energy # print(f'New best energy {energy} assigned') self.current_best_optimized_position = final_coords self.current_best_raw_position = list( itertools.chain(*fragments_coords)) # if len( # self.sqm_umbrella_centers) == 0 and self.arranger is not None: # self.arranger.clean_swarm_memory() # self.gap_umbrella = None # self.gap_umbrella_centers = [] # self.sqm_umbrella_centers.append( # self.current_best_raw_position) self.best_mol = final_mol self.best_run_number = self.run_number else: energy = tabooed_energy self.append_position_to_memory(fragments_coords, energy) # coarse grained energy, # make potential energy surface simpler return energy
def calc_energy(self, fragments_coords): # Energy orders: # Tabooed(1.0E5) > Umbrella(7.0E4) > Layout (6.0E4) > HardSphere (5.0E4) > # gravity (4.0E4) > PM7 (-1.0E1) tabooed_energy = 1.0E5 self.current_raw_position = fragments_coords self.current_optimized_position = None if self.is_current_position_tabooed(position_type="raw"): return tabooed_energy if self.gap_umbrella is not None: gap_umbrella_energy = self.gap_umbrella.calc_energy( fragments_coords) if gap_umbrella_energy > self.gap_umbrella.base_energy - 100.0: return gap_umbrella_energy sqm_umbrella_energy = self.sqm_umbrella.calc_energy(fragments_coords) if sqm_umbrella_energy > self.sqm_umbrella.base_energy - 100.0: return sqm_umbrella_energy if self.force_ordered_fragment: energy = self.layout_order.calc_energy(fragments_coords) if energy > self.layout_order.base_energy - 100.0: return energy energy = self.lower_sphere.calc_energy(fragments_coords) if energy > self.lower_sphere.base_energy - 100.0: return energy if not self.contact_detector.is_contact(fragments_coords): energy = self.gravitation.calc_energy(fragments_coords) if energy > self.gravitation.base_energy - 100.0: self.build_or_extend_gap_umbrella( current_gap=energy - self.gravitation.base_energy, fragments_coords=fragments_coords) return energy memorized_energy = self.query_memory_positions(fragments_coords) if memorized_energy is not None: energy = memorized_energy else: mol = self._get_super_molecule(fragments_coords) try: energy, final_mol = self.run_mopac(mol) except: return tabooed_energy from rubicon.utils.ion_arranger.ion_arranger import IonPlacer final_coords = IonPlacer.normalize_molecule(final_mol) self.current_optimized_position = final_coords if self.is_current_position_tabooed(position_type="optimized"): self.taboo_current_position(raw_position_only=True) return tabooed_energy energy = round(energy, 3) if self.is_optimized_position_inside_the_best_promixity( final_coords): if energy < self.best_energy or self.current_best_optimized_position is None: self.best_energy = energy self.current_best_optimized_position = final_coords self.current_best_raw_position = list( itertools.chain(*fragments_coords)) if len(self.sqm_umbrella_centers ) == 0 and self.arranger is not None: self.arranger.clean_swarm_memory() self.gap_umbrella = None self.gap_umbrella_centers = [] self.sqm_umbrella_centers.append( self.current_best_raw_position) self.best_mol = final_mol self.best_run_number = self.run_number else: energy = tabooed_energy self.append_position_to_memory(fragments_coords, energy) # coarse grained energy, # make potential energy surface simpler return energy
class TestContactDetector(TestCase): def setUp(self): pymagen_sodium = Molecule(species=['Na'], coords=[[999.0, 999.0, 999.0]], charge=1) # noinspection PyProtectedMember sodium_obmol = BabelMolAdaptor(pymagen_sodium)._obmol acetoxyq_anion_qcout = QcOutput( os.path.join(test_dir, "acetoxyq_anion.out")) pymatgen_acetoxyq = acetoxyq_anion_qcout.data[0]["molecules"][-1] acetoxyq_obmol = BabelMolAdaptor(pymatgen_acetoxyq)._obmol tfsi_qcout = QcOutput(os.path.join(test_dir, "tfsi.qcout")) pymatgen_tfsi = tfsi_qcout.data[0]["molecules"][-1] # noinspection PyProtectedMember tfsi_obmol = BabelMolAdaptor(pymatgen_tfsi)._obmol fragments = [sodium_obmol, tfsi_obmol] nums_fragments = [1, 1] self.acetoxyq_natfsi_placer = IonPlacer(acetoxyq_obmol, fragments, nums_fragments, None) rad_util = AtomicRadiusUtils(covalent_radius_scale=3.0, metal_radius_scale=1.5) mol_radius = rad_util.get_radius(acetoxyq_obmol) cation_radius = rad_util.get_radius(sodium_obmol) anion_radius = rad_util.get_radius(tfsi_obmol) mol_coords = IonPlacer.normalize_molecule(acetoxyq_obmol) fragments_atom_radius = [cation_radius, anion_radius] nums_fragments = [1, 1] self.detector = ContactDetector(mol_coords, mol_radius, fragments_atom_radius, nums_fragments) def test_get_contact_matrix(self): c = [-40.0, 0.0, 0.0, 20.0, 0.0, 0.0, 1.0, 2.0] fragments_coords = self.acetoxyq_natfsi_placer.decode_solution(c) contact_matrix = self.detector._get_contact_matrix(fragments_coords) ans = np.zeros((3, 3), int) self.assertEqual(str(contact_matrix), str(ans)) c = [-20.0, 0.0, 0.0, 5.0, 0.0, 0.0, 1.0, 2.0] fragments_coords = self.acetoxyq_natfsi_placer.decode_solution(c) contact_matrix = self.detector._get_contact_matrix(fragments_coords) ans = np.array([[0, 0, 1], [0, 0, 0], [1, 0, 0]], int) self.assertEqual(str(contact_matrix), str(ans)) c = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 2.0] fragments_coords = self.acetoxyq_natfsi_placer.decode_solution(c) contact_matrix = self.detector._get_contact_matrix(fragments_coords) ans = np.array([[0, 1, 1], [1, 0, 1], [1, 1, 0]], int) self.assertEqual(str(contact_matrix), str(ans)) def test_get_distance_matrix(self): start = np.zeros((5, 5), int) start[0, 1] = 1 start[1, 2] = 1 start[1, 4] = 1 start[3, 4] = 1 start[1, 0] = 1 start[2, 1] = 1 start[4, 1] = 1 start[4, 3] = 1 floydAPSP = self.detector._get_distance_matrix(start) self.assertEqual((5, 5), floydAPSP.shape) self.assertEquals(1, floydAPSP[0, 1]) self.assertEquals(2, floydAPSP[0, 2]) self.assertEquals(3, floydAPSP[0, 3]) self.assertEquals(2, floydAPSP[0, 4]) self.assertEquals(1, floydAPSP[1, 2]) self.assertEquals(2, floydAPSP[1, 3]) self.assertEquals(1, floydAPSP[1, 4]) self.assertEquals(3, floydAPSP[2, 3]) self.assertEquals(2, floydAPSP[2, 4]) self.assertEquals(1, floydAPSP[3, 4]) def test_is_contact(self): c = [-20.0, 0.0, 0.0, 10.0, 0.0, 0.0, 1.0, 2.0] fragments_coords = self.acetoxyq_natfsi_placer.decode_solution(c) is_contact = self.detector.is_contact(fragments_coords) self.assertFalse(is_contact) c = [-20.0, 0.0, 0.0, 5.0, 0.0, 0.0, 1.0, 2.0] fragments_coords = self.acetoxyq_natfsi_placer.decode_solution(c) is_contact = self.detector.is_contact(fragments_coords) self.assertFalse(is_contact) c = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 2.0] fragments_coords = self.acetoxyq_natfsi_placer.decode_solution(c) is_contact = self.detector.is_contact(fragments_coords) self.assertTrue(is_contact)