Exemplo n.º 1
0
    def test_histogram_scale(self):
        # Make a sample AB and AB2 cell
        cell1 = crystal.Cell(numpy.eye(3),
                             [numpy.zeros((1, 3)), 0.5 * numpy.ones((1, 3))])
        cell2 = crystal.Cell(numpy.eye(3), [numpy.zeros((1, 3)), \
            numpy.array([[0.35, 0.35, 0.35], [0.75, 0.75, 0.75]])])

        # Check similarity metric
        self.assertTrue(
            similarity.Histogram(6, 0.1, 0.999)((cell1, None), (cell1, None)))
        self.assertTrue(
            similarity.Histogram(6, 0.1, 0.999)(
                (cell1, None), (crystal.CellTools.tile(cell1,
                                                       (3, 2, 4)), None)))
        self.assertFalse(
            similarity.Histogram(6, 0.1, 0.999)((cell1, None), (cell2, None)))

        # Check numeric scaling
        histogram1 = similarity.Histogram(6, 0.1, 0.999)._compute_direct(cell1)
        histogram1s = similarity.Histogram(6, 0.1, 0.999)._compute_direct(
            crystal.CellTools.tile(cell1, (3, 2, 4)))
        histogram2 = similarity.Histogram(6, 0.1, 0.999)._compute_direct(cell2)
        self.assertTrue(numpy.all(numpy.isclose(histogram1, histogram1s)))
        self.assertTrue(
            numpy.all(numpy.isclose(histogram1[0, 1], histogram1[1, 0])))
        self.assertFalse(
            numpy.all(numpy.isclose(histogram2[0, 1], histogram2[1, 0])))
Exemplo n.º 2
0
 def test_scaling_processor(self):
     # ScalingProcessor should wrap CellTools.scale and Cell.scale_factor
     cell = crystal.Cell(numpy.eye(3),
                         [numpy.zeros((1, 3)), 0.5 * numpy.ones((1, 3))])
     new_radii = (3.4, 5.6)
     self.assertEqual(crystal.CellTools.scale(cell, cell.vectors / cell.scale_factor(new_radii)), \
         automation.ScalingProcessor(new_radii)(cell))
Exemplo n.º 3
0
    def test_histogram_correct(self):
        # Construct a histogram manually using cell RDF method
        cell = crystal.Cell(
            numpy.eye(3),
            [numpy.zeros((1, 3)),
             numpy.array([[0.3] * 3, [0.65] * 3])])
        histogram = numpy.zeros((2, 2, 20))
        for source in range(2):
            for target in range(2):
                for key, value in cell.rdf(source, target, 5).items():
                    factor = 0.5 + (4 * key) - int(numpy.round(4 * key))
                    histogram[source, target,
                              max(0,
                                  int(numpy.round(4 * key)) -
                                  1)] += value * (1 - factor)
                    histogram[source, target,
                              min(19, int(numpy.round(4 *
                                                      key)))] += value * factor

        # Construct a fast histogram and compare
        self.assertTrue(
            numpy.all(
                numpy.isclose(histogram,
                              potential._evaluate_fast(cell, None, 5,
                                                       0.25)[2])))
Exemplo n.º 4
0
    def test_cache(self):
        # Create a custom metric to keep track of cache hits
        cache_misses = [0]

        class CustomMetric(similarity.SimilarityMetric):
            def _compute_direct(self, cell):
                cache_misses[0] += 1
                return cell[1]

            def __call__(self, cell_1, cell_2):
                return self._compute_cached(cell_1) == self._compute_cached(
                    cell_2)

        # Create a dummy cell to make sure it can get hashed in cache
        cell = crystal.Cell(numpy.eye(3), [numpy.eye(3), numpy.eye(3)])

        # Test cache proper operation
        metric = CustomMetric()
        self.assertFalse(metric((cell, 1), (cell, 2)))
        self.assertFalse(metric((cell, 3), (cell, 4)))
        self.assertEqual(cache_misses[0], 4)
        self.assertFalse(metric((cell, 1), (cell, 4)))
        self.assertEqual(cache_misses[0], 4)
        self.assertFalse(metric((cell, 1), (cell, 5)))
        self.assertEqual(cache_misses[0], 5)
        self.assertTrue(metric((cell, 2), (cell, 2)))
        self.assertTrue(metric((cell, 5), (cell, 5)))
        self.assertEqual(cache_misses[0], 5)
Exemplo n.º 5
0
 def test_histogram_binning(self):
     # Check for proper binning (number of bins)
     cell = crystal.Cell(
         numpy.eye(3),
         [numpy.zeros((1, 3)),
          numpy.array([[0.3] * 3, [0.65] * 3])])
     self.assertEqual(
         potential._evaluate_fast(cell, None, 6, 0.25)[2].shape[2], 24)
     self.assertEqual(
         potential._evaluate_fast(cell, None, 6.01, 0.25)[2].shape[2], 25)
     self.assertEqual(
         potential._evaluate_fast(cell, None, 4, 5)[2].shape[2], 1)
Exemplo n.º 6
0
    def test_tile_wallpaper(self):
        # Create a chiral 2D cell
        reference_cell_1 = crystal.Cell(numpy.eye(2), \
            [numpy.array([[0.25, 0.25]]), numpy.array([[0.75, 0.25]]), numpy.array([[0.25, 0.75]])], ["O", "X", "Y"])
        a, b = 0.18469903125906464, 0.554097093777194 # to get nice contacts for right-angled 45-45-90 triangles
        reference_cell_2 = crystal.Cell(numpy.eye(2), \
            [numpy.array([[a, a]]), numpy.array([[b, a]]), numpy.array([[a, b]])], ["O", "X", "Y"])

        # Create the tilings (for possible visual inspection later)
        for group_index in range(17):
            group = wallpaper.WallpaperGroup(number=group_index + 1)

            # Determine what the cell vectors should look like
            length_ratio = group.ratio if group.ratio is not None else 1.25
            unit_dot = group.dot if group.dot is not None else 0.25
            vectors = numpy.array([[length_ratio, 0.0], [unit_dot, numpy.sqrt(1 - (unit_dot ** 2))]])

            # Do it
            tiling_cell = crystal.CellTools.scale(reference_cell_2 if group.half else reference_cell_1, vectors)
            tiled_cell = wallpaper.tile_wallpaper(tiling_cell, group)
            with open("data/group_{}.cell".format(group_index + 1), "w") as data_file:
                crystal.CellCodecs.write_cell(tiled_cell, data_file)
Exemplo n.º 7
0
    def test_methods_jacobian(self):
        for cell, potentials, cutoff, expected in EvaluateTests._cases:
            # First, make sure Python and Cython algorithms give identical answers
            cell = crystal.CellTools.reduce(cell)
            energy_slow = crystal.CellTools.energy(cell, potentials, cutoff)
            energy_fast, jacobian_fast = potential._evaluate_fast(
                cell, potentials, cutoff)
            self.assertAlmostEqual(energy_slow, energy_fast)
            if expected is not None:
                self.assertTrue(numpy.isclose(energy_fast, expected))

            # Now use second-order finite differences to make sure gradient is correct
            delta = 2.0**-26.0
            index = 0
            for type_index in range(cell.atom_types):
                for atom_index in range(cell.atom_count(type_index)):
                    for component_index in range(cell.dimensions):
                        low_lists, high_lists = cell.atom_lists, cell.atom_lists
                        low_lists[type_index][atom_index][
                            component_index] -= delta
                        high_lists[type_index][atom_index][
                            component_index] += delta
                        low_energy = potential._evaluate_fast(
                            crystal.CellTools.wrap(
                                crystal.Cell(cell.vectors, low_lists)),
                            potentials, cutoff)[0]
                        high_energy = potential._evaluate_fast(
                            crystal.CellTools.wrap(
                                crystal.Cell(cell.vectors, high_lists)),
                            potentials, cutoff)[0]
                        derivative = (high_energy - low_energy) / (delta * 2)
                        self.assertTrue(
                            numpy.isclose(derivative,
                                          jacobian_fast[index],
                                          atol=1e-4,
                                          rtol=1e-4))
                        index += 1
Exemplo n.º 8
0
 def test_filtering_processor(self):
     # AutoFilteringProcessor should do absolutely nothing when called
     # It will get removed from the preprocessing chain and handled separately
     cell = crystal.Cell(numpy.eye(3), [numpy.eye(3)] * 3)
     self.assertEqual(cell, automation.AutoFilteringProcessor(1)(cell))
Exemplo n.º 9
0
 def test_tiling_processor(self):
     # TilingProcessor should wrap CellTools.tile
     cell = crystal.Cell(numpy.eye(3), [numpy.eye(3)] * 3)
     self.assertEqual(crystal.CellTools.tile(cell, (4, 4, 4)),
                      automation.TilingProcessor((4, 4, 4))(cell))
Exemplo n.º 10
0
 def test_cell_processor(self):
     # CellProcessor should do absolutely nothing
     cell = crystal.Cell(numpy.eye(3), [numpy.eye(3)] * 3)
     self.assertEqual(cell, automation.CellProcessor()(cell))
Exemplo n.º 11
0
#!/usr/bin/env python

import itertools
import numpy
import unittest

from paccs import crystal
from paccs import visualization

_cells = [
    crystal.Cell(numpy.eye(3), [numpy.zeros((1, 3))]),
    crystal.Cell(numpy.eye(2), [numpy.zeros((1, 2)), 0.5 * numpy.ones(
        (1, 2))]),
    crystal.Cell(numpy.eye(3), [numpy.zeros((1, 3)), 0.5 * numpy.ones(
        (1, 3))]),
    crystal.Cell(
        numpy.eye(3),
        [numpy.concatenate([numpy.zeros(
            (1, 3)), numpy.ones((1, 3))])])
]


class Tests(unittest.TestCase):
    def test_cell(self):
        for cell in _cells:
            coordinates, colors, sizes, types, boxes = \
                visualization._cell(cell, [1] * cell.dimensions, [i + 1 for i in range(cell.atom_types)])

            # Make sure output is reasonable
            count = sum(cell.atom_counts)
            self.assertEqual(coordinates.shape[0], count)
Exemplo n.º 12
0
class EvaluateTests(unittest.TestCase):

    # Try many different cells
    _cases = [
        (crystal.Cell(2.1 * numpy.eye(3), [
            numpy.array([[0.01, 0.02, 0.03]]),
            numpy.array([[0.98, 0.97, 0.99]])
        ]), {
            (0, 0): potential.LennardJonesType(s=3.0**0.5, lambda_=-1),
            (1, 1): potential.LennardJonesType(s=3.0**0.5, lambda_=-1),
            (0, 1): potential.LennardJonesType(s=3.0**0.5)
        }, 6, None),
        (crystal.Cell(100 * numpy.eye(3),
                      [numpy.array([[49, 50, 50], [51, 50, 50]])]), {
                          (0, 0): potential.LennardJonesType(s=2)
                      }, 3, -0.5),
        (crystal.Cell(100 * numpy.eye(3),
                      [numpy.array([[49, 50, 50], [51, 50, 50]])]), {
                          (0, 0): potential.LennardJonesType()
                      }, 3, None),
        (crystal.Cell(100 * numpy.eye(3),
                      [numpy.array([[99, 50, 50], [1, 50, 50]])]), {
                          (0, 0): potential.LennardJonesType(s=2)
                      }, 3, -0.5),
        (crystal.Cell(100 * numpy.eye(3),
                      [numpy.array([[99, 50, 50], [1, 50, 50]])]), {
                          (0, 0): potential.LennardJonesType()
                      }, 3, None),
        (crystal.Cell(100 * numpy.eye(3), [
            numpy.array([[49, 49, 50], [51, 51, 50], [49, 51, 50],
                         [51, 49, 50]])
        ]), {
            (0, 0): potential.LennardJonesType()
        }, 3, None),
        (crystal.Cell(100 * numpy.eye(3), [
            numpy.array([[-1, -1, 50], [1, 1, 50], [-1, 1, 50], [1, -1, 50]])
        ]), {
            (0, 0): potential.LennardJonesType()
        }, 3, None),
        (crystal.Cell(numpy.array([[100, 0, 0], [100, 100, 0], [0, 0, 100]]), [
            numpy.array([[49, 49, 50], [51, 51, 50], [51, 49, 50],
                         [149, 51, 50]])
        ]), {
            (0, 0): potential.LennardJonesType()
        }, 3, None),
        (crystal.Cell(numpy.array([[100, 0, 0], [100, 100, 0], [0, 0, 100]]), [
            numpy.array([[49, 49, 50], [51, 51, 50]]),
            numpy.array([[51, 49, 50], [149, 51, 50]])
        ]), {
            (0, 0): potential.LennardJonesType(),
            (0, 1): potential.LennardJonesType(),
            (1, 1): potential.LennardJonesType(lambda_=-1)
        }, 3, None),
        (crystal.Cell(
            numpy.array([[100, 0, 0], [100, 100, 0], [100, 100, 100]]), [
                numpy.array([[100, 100, 100], [101, 101, 101], [102, 102, 102],
                             [103, 103, 103]])
            ]), {
                (0, 0): potential.LennardJonesType()
            }, 3, None),
        (crystal.Cell(numpy.eye(3), [0.5 * numpy.zeros((1, 3))]), {
            (0, 0): potential.LennardJonesType(s=1)
        }, 6, None),
        (crystal.Cell(numpy.array([[1, 0, 0], [6, 1, 0], [0, 0, 1]]),
                      [numpy.array([[3, 0.5, 0.5]])]), {
                          (0, 0): potential.LennardJonesType(s=1)
                      }, 6, None),
        (crystal.Cell(
            numpy.array([[1, 0.01, 0.02], [0.03, 1, 0.04], [0.05, 0.06, 1]]), [
                numpy.array([[0.25, 0.26, 0.27]]),
                numpy.array([[0.75, 0.76, 0.77]])
            ]), {
                (0, 0): potential.LennardJonesType(s=0.7, n=24),
                (1, 1): potential.LennardJonesType(s=0.8, n=12),
                (0, 1): potential.LennardJonesType(s=0.75, n=9)
            }, 6, None),
        (crystal.CellTools.wrap(
            crystal.Cell(
                numpy.array([[1, 0.01, 0.02], [0.03, 1, 0.04],
                             [0.05, 0.06, 1]]), [
                                 numpy.array([[0.95, 0.96, 0.97]]),
                                 numpy.array([[1.45, 1.46, 1.47]])
                             ])), {
                                 (0, 0): potential.LennardJonesType(s=0.7,
                                                                    n=24),
                                 (1, 1): potential.LennardJonesType(s=0.8,
                                                                    n=12),
                                 (0, 1): potential.LennardJonesType(s=0.75,
                                                                    n=9)
                             }, 6, None),
        (crystal.Cell(
            numpy.array([[1.1, 0.2, 0.4], [0.6, 1, 0.8], [1.2, 1.4, 1]]),
            [numpy.array([[1, 1, 1.1], [1.6, 1.8, 1.7]])]), {
                (0, 0): potential.LennardJonesType(s=0.3, n=24)
            }, 6, None),
        (crystal.Cell(
            numpy.array([[2.66703688, -0.32850482, -0.12184191],
                         [1.11351198, 1.61363475, 0.0948566],
                         [0.98523977, 0.40819993, 1.64547459]]),
            [
                numpy.array([[0.05395002, -0.09955472, -0.12233975]]),
                numpy.array([[0.76254656, 0.57095924, 0.45567309]])
            ]), {
                (0, 0): potential.LennardJonesType(lambda_=-1),
                (1, 1): potential.LennardJonesType(lambda_=-1),
                (0, 1): potential.LennardJonesType()
            }, 6, -1.33496937438),
        (crystal.Cell(
            numpy.array([[2.6899529, 0, 0], [0.90266756, 1.74296159, 0],
                         [0.85246376, 0.65541009, 1.63971167]]),
            [
                numpy.array([[0.07118973, -0.1012279, -0.1116857]]),
                numpy.array([[0.66568335, 0.69580262, 0.43339827]])
            ]), {
                (0, 0): potential.LennardJonesType(lambda_=-1),
                (1, 1): potential.LennardJonesType(lambda_=-1),
                (0, 1): potential.LennardJonesType()
            }, 6, -1.33496937438),
    ]

    def test_methods_jacobian(self):
        for cell, potentials, cutoff, expected in EvaluateTests._cases:
            # First, make sure Python and Cython algorithms give identical answers
            cell = crystal.CellTools.reduce(cell)
            energy_slow = crystal.CellTools.energy(cell, potentials, cutoff)
            energy_fast, jacobian_fast = potential._evaluate_fast(
                cell, potentials, cutoff)
            self.assertAlmostEqual(energy_slow, energy_fast)
            if expected is not None:
                self.assertTrue(numpy.isclose(energy_fast, expected))

            # Now use second-order finite differences to make sure gradient is correct
            delta = 2.0**-26.0
            index = 0
            for type_index in range(cell.atom_types):
                for atom_index in range(cell.atom_count(type_index)):
                    for component_index in range(cell.dimensions):
                        low_lists, high_lists = cell.atom_lists, cell.atom_lists
                        low_lists[type_index][atom_index][
                            component_index] -= delta
                        high_lists[type_index][atom_index][
                            component_index] += delta
                        low_energy = potential._evaluate_fast(
                            crystal.CellTools.wrap(
                                crystal.Cell(cell.vectors, low_lists)),
                            potentials, cutoff)[0]
                        high_energy = potential._evaluate_fast(
                            crystal.CellTools.wrap(
                                crystal.Cell(cell.vectors, high_lists)),
                            potentials, cutoff)[0]
                        derivative = (high_energy - low_energy) / (delta * 2)
                        self.assertTrue(
                            numpy.isclose(derivative,
                                          jacobian_fast[index],
                                          atol=1e-4,
                                          rtol=1e-4))
                        index += 1

    def test_histogram_correct(self):
        # Construct a histogram manually using cell RDF method
        cell = crystal.Cell(
            numpy.eye(3),
            [numpy.zeros((1, 3)),
             numpy.array([[0.3] * 3, [0.65] * 3])])
        histogram = numpy.zeros((2, 2, 20))
        for source in range(2):
            for target in range(2):
                for key, value in cell.rdf(source, target, 5).items():
                    factor = 0.5 + (4 * key) - int(numpy.round(4 * key))
                    histogram[source, target,
                              max(0,
                                  int(numpy.round(4 * key)) -
                                  1)] += value * (1 - factor)
                    histogram[source, target,
                              min(19, int(numpy.round(4 *
                                                      key)))] += value * factor

        # Construct a fast histogram and compare
        self.assertTrue(
            numpy.all(
                numpy.isclose(histogram,
                              potential._evaluate_fast(cell, None, 5,
                                                       0.25)[2])))

    def test_histogram_binning(self):
        # Check for proper binning (number of bins)
        cell = crystal.Cell(
            numpy.eye(3),
            [numpy.zeros((1, 3)),
             numpy.array([[0.3] * 3, [0.65] * 3])])
        self.assertEqual(
            potential._evaluate_fast(cell, None, 6, 0.25)[2].shape[2], 24)
        self.assertEqual(
            potential._evaluate_fast(cell, None, 6.01, 0.25)[2].shape[2], 25)
        self.assertEqual(
            potential._evaluate_fast(cell, None, 4, 5)[2].shape[2], 1)

    def test_double(self):
        # Simple check with pairwise interaction direction
        energy, jacobian = potential._evaluate_fast(
            *EvaluateTests._cases[2][:3])
        self.assertLess(jacobian[0], 0)
        self.assertGreater(jacobian[3], 0)

    def test_double_wrap(self):
        # Make sure wrapping is working properly
        energy, jacobian = potential._evaluate_fast(
            *EvaluateTests._cases[4][:3])
        self.assertLess(jacobian[0], 0)
        self.assertGreater(jacobian[3], 0)

    def test_skewed(self):
        # Make sure that highly distorted cells evaluate properly
        energy_1, jacobian_1 = potential._evaluate_fast(
            *EvaluateTests._cases[10][:3])
        energy_2, jacobian_2 = potential._evaluate_fast(
            *EvaluateTests._cases[11][:3])
        self.assertTrue(numpy.all(numpy.isclose(energy_1, energy_2)))
        self.assertTrue(numpy.all(numpy.isclose(jacobian_1, jacobian_2)))

    def test_translated(self):
        # Make sure that an arbitrary translation does not affect anything
        energy_1, jacobian_1 = potential._evaluate_fast(
            *EvaluateTests._cases[12][:3])
        energy_2, jacobian_2 = potential._evaluate_fast(
            *EvaluateTests._cases[13][:3])
        self.assertTrue(numpy.all(numpy.isclose(energy_1, energy_2)))
        self.assertTrue(numpy.all(numpy.isclose(jacobian_1, jacobian_2)))