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)))
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_filter_actual_energy(self): generator = wallpaper.generate_wallpaper((1, 1), place_max=5, sample_count=100) result = [None] def callback(energies): result[0] = energies potentials = { (0, 0): potential.LennardJonesType(lambda_=-1), (1, 1): potential.LennardJonesType(lambda_=-1), (0, 1): potential.LennardJonesType(lambda_=1) } distance = 4.0 filter = minimization.filter(generator, potentials, distance, 20, histogram_callback=callback) # Make sure true energies are actually less than cutoff filter_results = list(filter) # Exhaust generator to trigger callback energies = result[0] for cell in filter_results: self.assertLessEqual( potential._evaluate_fast(cell[1], potentials, distance)[0], min(energies[20:]))
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_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_filter_generator(self): count = 100 distance = 3.0 radii = (2.**(1. / 6.) / 2., 2.**(1. / 6.) / 2.) potentials = { (0, 0): potential.LennardJonesType(epsilon=0), (1, 1): potential.LennardJonesType(epsilon=1), (0, 1): potential.LennardJonesType(epsilon=0.5) } mm = similarity.Histogram(distance, 0.05, 0.99, norm=similarity.Minimum()) # Generate an ensemble of candidates generator = wallpaper.generate_wallpaper( (1, 1), place_max=4, random_seed=0, sample_count=count, merge_sets=False, sample_groups=[wallpaper.WallpaperGroup(name="p3")]) results = list(generator) # All "count" structures should be provided self.assertEqual(len(results), count) # Scale cells to "contact" scale_cell = lambda cell: crystal.CellTools.scale( cell, cell.vectors / cell.scale_factor(radii)) cells = [scale_cell(c) for g, c in results] energies = numpy.array([ potential._evaluate_fast(c, potentials, distance)[0] for c in cells ]) res = zip(cells, energies) # Find "unique" ones reduced_cells = similarity.reduce(res, mm) manually_reduced = len(reduced_cells) self.assertEqual(manually_reduced, 89) # Do in an automated fashion to compare generator2 = wallpaper.generate_wallpaper( (1, 1), place_max=4, random_seed=0, sample_count=count, merge_sets=False, sample_groups=[wallpaper.WallpaperGroup(name="p3")]) filter2 = minimization.filter(generator2, potentials, distance, count, radii, similarity_metric=mm) self.assertEqual(len(list(filter2)), manually_reduced) # Confirm that cells from automatic reduction have not been rescaled for idx, (g, c) in enumerate(list(filter2)): self.assertTrue(c != reduced_cells[idx][0]) self.assertTrue(scale_cell(c) == reduced_cells[idx][0]) self.assertTrue( potential._evaluate_fast(scale_cell(c), potentials, distance) [0] == reduced_cells[idx][1])
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_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)