예제 #1
0
 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)
예제 #2
0
    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[:]
예제 #3
0
    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
예제 #4
0
 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
예제 #5
0
    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
예제 #6
0
    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
예제 #7
0
    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
예제 #8
0
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)