Exemplo n.º 1
0
    def minimize(self, cluster: Cluster, *args, **kwargs) -> Cluster:
        """
        Method to locally minimise a cluster of Lennard-Jones particles.
        Uses the L-BFGS-B method implemented within scipy.minimize.


        Args:
            cluster: Cluster instance, required, cluster instance to be minimized
            kwargs: Dict containing any other keyword arguments to be passed to the scipy optimizer

        Returns:
            result_dict{'coordinates': optimised structure coordinates,
                    'energy': final energy of the cluster,
                    'success': True if successfully minimised}

        """
        coords, ids, labels = cluster.get_particle_positions()
        coordinates = coords

        result = minimize(fun=self.get_energy,
                          x0=coordinates.flatten(),
                          method='L-BFGS-B',
                          jac=self.get_jacobian,
                          *args,
                          **kwargs)

        if not result.success:
            print("Optimization failed")

        cluster.set_particle_positions(
            (result.x.reshape(coordinates.shape), ids, labels))
        cluster.cost = result.fun
        return cluster
Exemplo n.º 2
0
    def setUpClass(cls) -> None:
        """Sets up Deaven Ho mating for testing"""

        cls.log = logging.getLogger(__name__)
        cls.mate = DeavenHoCrossover(max_attempts=100)

        cls.seed = 1

        cls.c1 = Cluster(cost=-3.5,
                         molecules=[Molecule(np.array([[0., 0, 0], [0, 4, 0]]), ["H", "H"]),
                                    Molecule(np.array([[0., 0, 1], [0, 3, 0]]), ["H", "H"]),
                                    Molecule(np.array([[0., 0, 2], [0, 2, 0]]), ["Cr", "H"]),
                                    Molecule(np.array([[0., 0, 3], [0, 1, 0]]), ["H", "H"]),
                                    Molecule(np.array([[0., 0, 4], [0, 0, 0]]), ["H", "H"])])

        cls.c2 = Cluster(cost=-3.5,
                         molecules=[Molecule(np.array([[4., 0, 0], [0, 0, 4]]), ["H", "H"]),
                                    Molecule(np.array([[3., 0, 1], [1, 0, 2]]), ["H", "H"]),
                                    Molecule(np.array([[2., 0, 2], [2, 0, 2]]), ["H", "Cr"]),
                                    Molecule(np.array([[1., 0, 3], [3, 0, 1]]), ["H", "H"]),
                                    Molecule(np.array([[0., 2, 4], [4, 0, 1]]), ["H", "H"])])

        cls.c3 = Cluster(cost=-3.5,
                         molecules=[Molecule(np.array([[0., 1, 0], [5, 4, 3]]), ["H", "H"]),
                                    Molecule(np.array([[1., 2, 1], [4, 3, 4]]), ["H", "H"]),
                                    Molecule(np.array([[2., 3, 2], [3, 2, 5]]), ["Cr", "H"]),
                                    Molecule(np.array([[3., 4, 3], [2, 1, 6]]), ["H", "H"]),
                                    Molecule(np.array([[4., 5, 4], [1, 0, 7]]), ["H", "H"])])
Exemplo n.º 3
0
    def minimize(self, cluster: Cluster, *args, **kwargs) -> Cluster:
        """
        Method to locally minimise a cluster of Lennard-Jones particles.
        Uses the L-BFGS-B method implemented within scipy.minimize.

        Attributes:
            coordinates: np.array(shape=(number_of_particles, 3), dtype=float) array of coordinates
            kwargs: Dict containing any other keyword arguments to be passed to the scipy optimizer
            molecules: list(int), optional,

        Returns
        -------
        result_dict{'coordinates': optimised structure coordinates,
                    'energy': final energy of the cluster,
                    'success': True if successfully minimised}

        """
        positions = list(cluster.get_particle_positions())
        coordinates = positions[0].flatten()

        # args = {"sigma": self.sigma, "epsilon": self.epsilon4, "base_exp": 6}

        result = scipy.optimize.minimize(
            fun=self.get_energy,
            x0=coordinates,  # , args=args,
            method='L-BFGS-B',
            jac=self.get_jacobian)

        positions = (result.x.reshape(
            (self.n_atoms, 3)), positions[1], positions[2])
        cluster.set_particle_positions(positions)
        cluster.cost = result.fun
        return cluster
Exemplo n.º 4
0
    def get_energy(self, cluster: Cluster) -> float:
        """
        Method to return the single-point energy of a system

        Parameters
        ----------


        Returns
        -------
        float(energy): Energy of the system at the given coordinates

        Args:
            cluster: Cluster instance, required, the for which to calculate energy
            *args: list, optional, postitional arguments
            **kwargs: Other keyword arguments needed on a per-implementation basis (i.e. atom labels)

        """
        if isinstance(cluster, Cluster):
            coordinates, _, _ = cluster.get_particle_positions()
        elif isinstance(cluster, np.ndarray):
            natoms = int(len(cluster) / 3)
            coordinates = cluster.reshape((natoms, 3))
        else:
            raise AttributeError("coordinate format is not accepted")

        rs = get_all_magnitudes(coordinates)
        coulombic = self.coulombic_E_component(rs)

        LJ_component = self.LJ_E_component(rs)
        return coulombic + LJ_component
Exemplo n.º 5
0
    def test_simple_geometric_characterizer_similar_cluster_succeed(self) -> None:

        compare = SimpleGeometricCharacterizer()

        c1 = Cluster(cost=0.0, molecules=[Molecule(coordinates=np.array([[1.0, 0.0, 0.0]]), particle_names=["LJ"]),
                                          Molecule(coordinates=np.array([[0.0, 1.0, 0.0]]), particle_names=["LJ"]),
                                          Molecule(coordinates=np.array([[0.0, 0.0, -1.0]]), particle_names=["LJ"])])

        c2 = Cluster(cost=0.0, molecules=[Molecule(coordinates=np.array([[-1.0, 2e-1, 1e-1]]), particle_names=["LJ"]),
                                          Molecule(coordinates=np.array([[5e-2, -1.0, 1e-1]]), particle_names=["LJ"]),
                                          Molecule(coordinates=np.array([[1e-2, 0.0, 1.1]]), particle_names=["LJ"])])

        self.assertTrue(compare(c1, c2))
Exemplo n.º 6
0
    def test_simple_geometric_characterizer_nearly_same_cluster_fail(self) -> None:

        compare = SimpleGeometricCharacterizer()

        c1 = Cluster(cost=0.0, molecules=[Molecule(coordinates=np.array([[1.0, 0.0, 0.0]]), particle_names=["LJ"]),
                                          Molecule(coordinates=np.array([[0.0, 1.0, 0.0]]), particle_names=["LJ"]),
                                          Molecule(coordinates=np.array([[0.0, 0.0, -1.0]]), particle_names=["LJ"])])

        c2 = Cluster(cost=0.0, molecules=[Molecule(coordinates=np.array([[-1.0, 0.1, -0.1]]), particle_names=["LJ"]),
                                          Molecule(coordinates=np.array([[0.0, -1.0, 0.0]]), particle_names=["LJ"]),
                                          Molecule(coordinates=np.array([[0.1, -0.1, 1.1]]), particle_names=["LJ"])])

        self.assertFalse(compare(c1, c2))
Exemplo n.º 7
0
    def test_RST_mutate_good(self) -> None:

        c1 = Cluster(cost=9.0,
                     molecules=[Molecule(coordinates=np.random.uniform(low=10, size=(2, 3)),
                                         particle_names=["B", "Be"]),
                                Molecule(coordinates=np.random.uniform(low=10, size=(3, 3)),
                                         particle_names=["Be", "B", "Be"])])

        mutation = RandomSingleTranslation()
        new_cluster = mutation.mutate(copy.deepcopy(c1))

        self.assertIsInstance(new_cluster, Cluster)
        self.assertFalse(np.allclose(new_cluster.get_molecular_positions()[0], c1.get_molecular_positions()[0]))
Exemplo n.º 8
0
    def test_parse_structures_list_clusters(self) -> None:
        c1 = Cluster(cost=0.0,
                     molecules=[Molecule(coordinates=np.zeros(shape=(2, 3)), particle_names=["H", "He"]),
                                Molecule(coordinates=np.zeros(shape=(3, 3)), particle_names=["H", "H", "He"])])

        c2 = Cluster(cost=9.0,
                     molecules=[Molecule(coordinates=np.ones(shape=(2, 3)), particle_names=["B", "Be"]),
                                Molecule(coordinates=np.ones(shape=(3, 3)), particle_names=["Be", "B", "Be"])])
        cluster_list = [c1, c2]

        output = self.writer._parse_structures(cluster_list)
        self.assertListEqual(output[0][1][0].tolist(), np.zeros(shape=(5, 3)).tolist())  # Check coords are correct
        self.assertListEqual(output[1], [0, 9])
Exemplo n.º 9
0
    def test_lj_energy_r_min(self) -> None:
        # Then check we get v~-1 @ r~r_{min} (r_min = 2**(1./exp_attractive))
        c1 = Cluster(cost=0.0, molecules=[Molecule(coordinates=np.array([[0.0, 0.0, 0.0]]),
                                                   particle_names=["LJ"]),
                                          Molecule(coordinates=np.array([[2**(1./6.0), 0.0, 0.0]]),
                                                   particle_names=["LJ"])])

        c2 = Cluster(cost=0.0, molecules=[Molecule(coordinates=np.array([[0.0, 0.0, 0.0]]),
                                                   particle_names=["LJ"]),
                                          Molecule(coordinates=np.array([[2 ** (1. / 20.), 0.0, 0.0]]),
                                                   particle_names=["LJ"])])

        self.assertAlmostEqual(-1.0, self.LJ_6_12.get_energy(c1))
        self.assertAlmostEqual(-1.0, self.LJ_15_30.get_energy(c2))
Exemplo n.º 10
0
    def test_get_energy_GLJ_zero(self):
        pot = OPLS_potential(q=[0, 0], eps=[1, 1], sigma=[1, 1])

        # GLJ energy at r_ij=1.0 == 0.0 eV
        clus1 = Cluster(cost=0.0, molecules=[Molecule(coordinates=np.array([[0.0, 0.0, 0.0], [0.0, 0.0, 1.0]]),
                                                      particle_names=["LJ", "LJ"])])

        self.assertEqual(pot.get_energy(clus1), 0.0)

        # At large r, en ~~ 0.0
        clus2 = Cluster(cost=0.0, molecules=[Molecule(coordinates=np.array([[0.0, 0.0, 0.0], [0.0, 0.0, 1e99]]),
                                                      particle_names=["LJ", "LJ"])])

        self.assertEqual(pot.get_energy(clus2), 0)
Exemplo n.º 11
0
    def test__get_coord_labels(self) -> None:

        c1 = Cluster(cost=0.0,
                     molecules=[Molecule(coordinates=np.zeros(shape=(2, 3)), particle_names=["H", "He"]),
                                Molecule(coordinates=np.zeros(shape=(3, 3)), particle_names=["H", "H", "He"])])

        c2 = Cluster(cost=0.0,
                     molecules=[Molecule(coordinates=np.ones(shape=(2, 3)), particle_names=["B", "Be"]),
                                Molecule(coordinates=np.ones(shape=(3, 3)), particle_names=["Be", "B", "Be"])])
        cluster_list = [c1, c2]
        coord_labels = self.writer._get_coord_labels(cluster_list)

        self.assertListEqual(list(coord_labels[0][0][0]), [0, 0, 0])
        self.assertTrue("Be" in coord_labels[1][1])
Exemplo n.º 12
0
    def test_shake_mutate_good(self) -> None:
        c1 = Cluster(cost=9.0,
                     molecules=[Molecule(coordinates=np.random.uniform(low=10, size=(2, 3)),
                                         particle_names=["B", "Be"]),
                                Molecule(coordinates=np.random.uniform(low=10, size=(3, 3)),
                                         particle_names=["Be", "B", "Be"])])

        mutation = Shake()

        mutated_c1 = mutation.mutate(copy.deepcopy(c1))

        diff = c1.get_particle_positions()[0] - mutated_c1.get_particle_positions()[0]

        self.assertEqual(magnitude(diff[0]), 0.42059300827254525)
        self.assertEqual(magnitude(diff[-1]), 0.4186786088973787)
Exemplo n.º 13
0
    def test_minimise(self):
        if self.executable is None:
            self.skipTest("Executable not found. Minimise test skipped.")

        testdir = "test_dftb"
        if os.path.exists(testdir):
            shutil.rmtree(testdir)
        os.mkdir(testdir)

        clus1 = Cluster(molecules=[
            Molecule(particle_names=["H", "H", "O"],
                     coordinates=np.array([[0.0, 0.0, 1.0], [0.0, 0.0, -1.0],
                                           [0.0, 0.0, 0.0]])),
            Molecule(particle_names=["H", "H", "O"],
                     coordinates=np.array([[2.0, 0.0, 1.0], [2.0, 0.0, -1.0],
                                           [2.0, 0.0, 0.0]]))
        ])

        pot = DeMonDFTBPotential(minimize_template=self.test_data_path +
                                 "/dftb_in.hsd",
                                 energy_template="NONE",
                                 work_dir=".",
                                 run_string=self.executable)

        clus2 = pot.minimize(clus1, dir_name=testdir)

        coords, mol_ids, atom_names = clus2.get_particle_positions()

        self.assertListEqual(atom_names, ["H", "H", "O", "H", "H", "O"])

        if os.path.exists(testdir):
            shutil.rmtree(testdir)
Exemplo n.º 14
0
    def setUpClass(cls) -> None:
        """Sets up an instance of random cluster and a logger"""
        cls.log = logging.getLogger(__name__)
        cls.mutate = RandomCluster(log=cls.log)  # , box_length=10.0)

        cls.c1 = Cluster(cost=0.0,
                         molecules=[Molecule(coordinates=np.array([[1., 1, 1], [0, 0, 0]]),
                                             particle_names=["He", "H"]),
                                    Molecule(coordinates=np.array([[1., -1, -1], [0, 0, 0], [-1, -1, -1]]),
                                             particle_names=["H", "H", "He"])])

        cls.c2 = Cluster(cost=9.0,
                         molecules=[Molecule(coordinates=np.ones(shape=(2, 3)),
                                             particle_names=["B", "Be"]),
                                    Molecule(coordinates=np.zeros(shape=(3, 3)),
                                             particle_names=["Be", "B", "Be"])])
Exemplo n.º 15
0
    def test_parse_structures_single_cluster(self) -> None:
        c1 = Cluster(cost=0.0,
                     molecules=[Molecule(coordinates=np.zeros(shape=(2, 3)), particle_names=["H", "He"]),
                                Molecule(coordinates=np.zeros(shape=(3, 3)), particle_names=["H", "H", "He"])])

        output = self.writer._parse_structures(c1)
        self.assertListEqual(output[0][0][0].tolist(), np.zeros(shape=(5, 3)).tolist())  # Check coords are correct
Exemplo n.º 16
0
    def test_SGD_runs(self):

        writer = XYZWriter()
        pot = NewLJ(5)
        c1 = Cluster(molecules=[
            Molecule(coordinates=np.array(
                [[0.566474720473, 0.05189774298450, 0.03347914367068]]),
                     particle_names=["Cl"]),
            Molecule(coordinates=np.array(
                [[-0.010999390189086, 1.01397142828, -1.00418537828]]),
                     particle_names=["Cl"]),
            Molecule(coordinates=np.array(
                [[-0.555475330284, 0.0341308287337, 0.0623354819510]]),
                     particle_names=["Cl"]),
            Molecule(coordinates=np.array(
                [[-0.39523644062, 2.8659668824697, 0.3990951103299]]),
                     particle_names=["Cl"]),
            Molecule(coordinates=np.array(
                [[-0.39523644062, 0.8659668824697, 0.3990951103299]]),
                     particle_names=["Cl"])
        ], )
        sgd = SGD(potential=pot)

        c_ret = sgd(c1)
        writer.write(c_ret, "test_data/out.xyz")
        self.assertIsInstance(c_ret, Cluster)
        self.assertAlmostEqual(pot.get_energy(c_ret), -9.10385, places=3)
Exemplo n.º 17
0
    def test_lj_energy_r1(self) -> None:

        c1 = Cluster(cost=0.0, molecules=[Molecule(coordinates=np.array([[0.0, 0.0, 0.0]]), particle_names=["LJ"]),
                                          Molecule(coordinates=np.array([[1.0, 0.0, 0.0]]), particle_names=["LJ"])])
        # First we check that we get V=0 at r=1
        self.assertEqual(0.0, self.LJ_6_12.get_energy(c1))
        self.assertEqual(0.0, self.LJ_15_30.get_energy(c1))
Exemplo n.º 18
0
    def test_get_energy_GLJ_minimum(self):
        # GLJ energy at r_ij~1.112 ~~ -1.0 eV

        pot = OPLS_potential(q=[0, 0], eps=[1, 1], sigma=[1, 1])

        clus = Cluster(cost=0.0, molecules=[Molecule(coordinates=np.array([[0.0, 0.0, 0.0], [0.0, 0.0, 2**(1/6)]]),
                                                     particle_names=["LJ", "LJ"])])
        self.assertEqual(pot.get_energy(clus), -1)
Exemplo n.º 19
0
    def test_get_energy_coulombic_unlike_charges(self):

        pot = OPLS_potential(q=[1, -1], eps=[0, 0], sigma=[1, 1])

        clus = Cluster(cost=0.0, molecules=[Molecule(coordinates=np.array([[0.0, 0.0, 0.0], [0.0, 0.0, 0.1]]),
                                                     particle_names=["LJ", "LJ"])])

        self.assertLess(pot.get_energy(clus), 0)
Exemplo n.º 20
0
    def test_get_energy_GLJ_close_contact(self):
        # At small r, en >> 0.0

        pot = OPLS_potential(q=[0, 0], eps=[1, 1], sigma=[1, 1])

        clus = Cluster(cost=0.0, molecules=[Molecule(coordinates=np.array([[0.0, 0.0, 0.0], [0.0, 0.0, 0.1]]),
                                                     particle_names=["LJ", "LJ"])])

        self.assertGreater(pot.get_energy(clus), 1e3)
Exemplo n.º 21
0
    def test_ljc_get_jacobian_1(self) -> None:
        fast_potential = LJcPotential(2)

        c1 = Cluster(cost=0.0,
                     molecules=[
                         Molecule(coordinates=np.array([[0.0, 0.0, 0.0]]),
                                  particle_names=["LJ"]),
                         Molecule(coordinates=np.array(
                             [[2**(1 / 6.), 0.0, 0.0]]),
                                  particle_names=["LJ"])
                     ])

        test_jac = fast_potential.get_jacobian(
            c1.get_particle_positions()[0].flatten())

        # print(ref_jac, test_jac)
        self.assertEqual(
            np.array([-12.0, 0.0, 0.0, 12.0, 0.0, 0.0]).all(), test_jac.all())
Exemplo n.º 22
0
    def check_cluster(self, cluster: Cluster) -> bool:
        """Simple distance check to ensure that there is no particle overlap"""

        all_r_sq = (cluster.get_particle_positions()[0]**2).sum(-1)

        if min(all_r_sq) <= self.cutoff:
            return False
        else:
            return True
Exemplo n.º 23
0
    def test_simple_energy_characterizer(self) -> None:
        """Tests the simplest characterizer, based simply on energy"""
        c1 = Cluster(cost=-100, molecules=[])
        c2 = Cluster(cost=-99.9, molecules=[])
        c3 = Cluster(cost=-99.9+1e-6, molecules=[])
        c4 = Cluster(cost=-99.9+2e-6, molecules=[])

        # noinspection PyArgumentEqualDefault
        simple_characterizer = SimpleEnergeticCharacterizer(accuracy=1e-6)  # default accuracy=1e-6 shown for clarity

        # c1 == c1
        self.assertTrue(simple_characterizer(c1, c1))
        # c2 is very close in energy to c3
        self.assertTrue(simple_characterizer(c2, c3))
        # c1 and c2 are distant in energy
        self.assertFalse(simple_characterizer(c1, c2))
        # c2 and c4 are above the threshold apart from each other
        self.assertFalse(simple_characterizer(c2, c4))
Exemplo n.º 24
0
    def test_minimize_LJ38(self) -> None:

        lj38_coordinates = np.loadtxt(bmpga.__path__[0]+"/tests/test_data/LJ38.xyz")

        c1 = Cluster(cost=0.0, molecules=[Molecule(coordinates=np.array([coord]),
                                                   particle_names=["LJ"]) for coord in lj38_coordinates])

        min_lj38 = self.LJ_6_12.minimize(c1)

        self.assertAlmostEqual(-173.928427, min_lj38['energy'], places=6)
Exemplo n.º 25
0
    def test_minimise_dimer(self) -> None:
        c1 = Cluster(cost=0.0, molecules=[Molecule(coordinates=np.array([[0.0, 0.0, 0.0]]),
                                                   particle_names=["LJ"]),
                                          Molecule(coordinates=np.array([[2**(1./6.0), 0.0, 0.0]]),
                                                   particle_names=["LJ"])])

        min1 = self.LJ_6_12.minimize(c1)

        self.assertTrue(min1['success'])
        self.assertAlmostEqual((2**(1./6.)), magnitude(min1['coordinates'][0], min1['coordinates'][1]))
Exemplo n.º 26
0
    def compare(self, cluster1: Cluster, cluster2: Cluster, *args,
                **kwargs) -> bool:
        """Simple geometry comparison.

        Aligns clusters, then

        Args:
            cluster1, (Cluster): required
            cluster2, (Cluster): required

        Returns:
            bool, True if the clusters are the same to within self.accuracy, else False

        """
        align_clusters(cluster1, cluster2)
        g_tensor_c1 = gyration_tensor(cluster1.get_particle_positions()[0])
        g_tensor_c2 = gyration_tensor(cluster2.get_particle_positions()[0])
        g_tensor_c1 -= g_tensor_c2

        return np.linalg.norm(g_tensor_c1) <= self.accuracy
Exemplo n.º 27
0
    def test_minimize_full(self):
        pot = OPLS_potential(q=[0.5, -0.5], eps=[1., 1.], sigma=[1., 1.])

        clus = Cluster(cost=0.0,
                       molecules=[Molecule(coordinates=np.array([[0.1, 0.1, 0.], [0.2, 0.2, 1.122]]),
                                           particle_names=["LJ", "LJ"])])

        res = pot.minimize(clus)
        print(res)
        self.assertTrue(res['success'])
        self.assertLess(res["energy"], -1.0)
Exemplo n.º 28
0
    def test_minimize_3LJ(self) -> None:

        c1 = Cluster(cost=0.0, molecules=[Molecule(coordinates=np.array([[0.0, 0.0, 0.0]]),
                                                   particle_names=["LJ"]),
                                          Molecule(coordinates=np.array([[1.0, 0.0, 0.0]]),
                                                   particle_names=["LJ"]),
                                          Molecule(coordinates=np.array([[0.5, 0.5, 0.0]]),
                                                   particle_names=["LJ"])])

        min2 = self.LJ_6_12.minimize(c1)

        self.assertAlmostEqual(-3, min2['energy'])
Exemplo n.º 29
0
    def test_DH_crossover_same_labels(self) -> None:

        c1 = Cluster(cost=-3.5,
                     molecules=[Molecule(np.array([[0., 0, 0], [0, 4, 0]]), ["C", "H"]),
                                Molecule(np.array([[0., 0, 1], [0, 3, 0]]), ["C", "H"]),
                                Molecule(np.array([[0., 0, 2], [0, 2, 0]]), ["C", "H"]),
                                Molecule(np.array([[0., 0, 3], [0, 1, 0]]), ["C", "H"]),
                                Molecule(np.array([[0., 0, 4], [0, 0, 0]]), ["C", "H"])])

        c2 = Cluster(cost=-3.5,
                     molecules=[Molecule(np.array([[4., 0, 0], [0, 0, 4]]), ["H", "C"]),
                                Molecule(np.array([[3., 0, 1], [1, 0, 3]]), ["H", "C"]),
                                Molecule(np.array([[2., 0, 2], [2, 0, 1]]), ["H", "C"]),
                                Molecule(np.array([[1., 0, 3], [3, 0, 1]]), ["H", "C"]),
                                Molecule(np.array([[0., 2, 4], [4, 0, 0]]), ["H", "C"])])

        child = self.mate([c1, c2], n_crossover=1)

        self.log.debug(child.molecules)
        self.log.debug(child.get_molecular_positions())
        self.log.debug(child.get_particle_positions())
Exemplo n.º 30
0
    def get_energy(self, cluster: Cluster, *args, **kwargs) -> Cluster:
        """Provides the interface between the client and the minimise method of the

        Args:
            cluster: Cluster object, required, the Cluster to be minimised

        Returns:

        """
        self.log.debug("Getting energy for cluster: {}".format(cluster))

        # noinspection PyUnresolvedReferences
        result = self.potential.get_energy(cluster)
        cluster.cost = result
        return cluster