def test_filter_callback(self): generator = wallpaper.generate_wallpaper((1, 1), place_max=5, sample_count=100) result = [None] def callback(energies): result[0] = energies filter = minimization.filter( generator, { (0, 0): potential.LennardJonesType(lambda_=-1), (1, 1): potential.LennardJonesType(lambda_=-1), (0, 1): potential.LennardJonesType(lambda_=1) }, 4.0, 10, histogram_callback=callback) # Check for proper filtering behavior self.assertEqual(len(list(filter)), 10) # Get energies (callback should have been triggered) energies = result[0] sorted_energies = sorted(energies) # Check partitioning self.assertEqual(energies[10], sorted_energies[10]) # Did partition get target? self.assertLessEqual(max(energies[:10]), min( energies[10:])) # Did partition move elements?
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_n(self): # Check potential sharpness changing reference_r = numpy.linspace(0.75, 2, 100) last_u = potential.LennardJonesType().evaluate_array(reference_r)[0] for n in numpy.linspace(6, 96, 10)[1:]: test_u = potential.LennardJonesType( n=n).evaluate_array(reference_r)[0] self.assertTrue(numpy.all(test_u >= last_u)) last_u = test_u
def test_s(self): # Check horizontal shift reference_r = numpy.linspace(0.75, 2, 100) reference_u, reference_f = potential.LennardJonesType( s=1.0).evaluate_array(reference_r) for s in numpy.linspace(0.5, 2.5, 10): test_u, test_f = potential.LennardJonesType( s=s).evaluate_array(reference_r + s - 1.0) self.assertTrue(numpy.all(numpy.isclose(reference_u, test_u))) self.assertTrue(numpy.all(numpy.isclose(reference_f, test_f)))
def test_sigma(self): # Check length scaling reference_r = numpy.linspace(0.75, 2, 100) reference_u, reference_f = potential.LennardJonesType().evaluate_array( reference_r) for sigma in numpy.linspace(0.5, 3, 10): test_u, test_f = potential.LennardJonesType( sigma=sigma).evaluate_array(reference_r * sigma) self.assertTrue(numpy.all(numpy.isclose(reference_u, test_u))) self.assertTrue( numpy.all(numpy.isclose(reference_f, test_f * sigma)))
def test_lambda(self): # Check shape factor reference_r = numpy.linspace(0.75, 2, 100) last_u, last_f = potential.LennardJonesType().evaluate_array( reference_r) for lambda_ in numpy.linspace(-1, 1, 10)[::-1][1:]: test_u, test_f = potential.LennardJonesType( lambda_=lambda_).evaluate_array(reference_r) self.assertTrue(numpy.all(test_u > last_u)) self.assertTrue(numpy.all(test_f > last_f)) last_u, last_f = test_u, test_f
def test_filter_radii(self): generator = wallpaper.generate_wallpaper((1, 1), place_max=5, sample_count=100) filter = minimization.filter( generator, { (0, 0): potential.LennardJonesType(lambda_=-1), (1, 1): potential.LennardJonesType(lambda_=-1), (0, 1): potential.LennardJonesType(lambda_=1) }, 4.0, 10, (0.5, 0.5)) self.assertEqual(len(list(filter)), 10)
def test_epsilon(self): # Check energy scaling reference_r = numpy.linspace(0.75, 2, 100) reference_u, reference_f = potential.LennardJonesType().evaluate_array( reference_r) for epsilon in numpy.linspace(0.5, 3, 10): test_u, test_f = potential.LennardJonesType( epsilon=epsilon).evaluate_array(reference_r) self.assertTrue( numpy.all(numpy.isclose(reference_u, test_u / epsilon))) self.assertTrue( numpy.all(numpy.isclose(reference_f, test_f / epsilon)))
def test_cluster_move(self): for cell in _cells: minimization.optimize( cell, { (0, 0): potential.LennardJonesType(lambda_=-1), (1, 1): potential.LennardJonesType(lambda_=-1), (0, 1): potential.LennardJonesType() }, 6, log_level=2, basin_kwargs=dict(niter=10), exchange_move=0, vector_move=0, scale_move=0, atom_move=0, cluster_move=1)
def test_repulsive(self): # Check repulsive potential for lack of well potential_object = potential.LennardJonesType(s=1, lambda_=-1) self.assertTrue( numpy.all( potential_object.evaluate_array(numpy.linspace(0.5, 1.5, 100)) [1] > 0))
def test_force(self): # Check derivatives with finite difference approximation potential_object = potential.LennardJonesType(1.2, 3.4, 0.5, 6.7, 0.89) r = numpy.linspace(0.75, 2, 1000) u, f = potential_object.evaluate_array(r) f_approx = -numpy.gradient(u, r[1] - r[0]) self.assertTrue( numpy.all( numpy.isclose(f[1:-1], f_approx[1:-1], rtol=1e-3, atol=1e-3)))
def test_epsilon(self): # Check energy scaling and shifting potential1 = potential.LennardJonesType() potential2 = potential.Transform(potential1, epsilon=1.23, phi=4.56) r = numpy.linspace(0.9, 2, 100) u1, f1 = potential1.evaluate_array(r) u2, f2 = potential2.evaluate_array(r) self.assertTrue(numpy.all(numpy.isclose(u1, (u2 / 1.23) - 4.56))) self.assertTrue(numpy.all(numpy.isclose(f1, f2 / 1.23)))
def test_attractive(self): # Check attractive potential for well potential_object = potential.LennardJonesType(s=1) r1, r2 = numpy.linspace(0.5, 1, 100)[:-1], numpy.linspace(1, 1.5, 100)[1:] f1, f2 = potential_object.evaluate_array( r1)[1], potential_object.evaluate_array(r2)[1] self.assertTrue(numpy.all(f1 > 0)) self.assertTrue(numpy.all(f2 < 0))
def run_minimizations(test=None): for cell in _cells: if __name__ == "__main__": visualization.cell_mayavi(cell, [3] * cell.dimensions, [1] * cell.atom_types) from paccs import similarity results = minimization.optimize( cell, { (0, 0): potential.LennardJonesType(lambda_=-1, n=12), (1, 1): potential.LennardJonesType(lambda_=-1, n=12), (0, 1): potential.LennardJonesType(n=12) }, 6, log_level=2, initial_kwargs=dict(options=dict(disp=False)), # These options are chosen for testing speed, not accurate results! basin_kwargs=dict(T=0.3, niter=25, interval=5, niter_success=10, minimizer_kwargs=dict(options=dict(disp=False))), final_kwargs=dict(options=dict(disp=False)), save_count=10, save_filter=similarity.Energy(1e-2), save_all=False) last_result = results[-1] if test: test.assertLessEqual(len(results), 10) energies = [energy for cell, energy, wall, proc in results] for energy_index_1 in range(len(energies)): for energy_index_2 in range(energy_index_1 + 1, len(energies)): test.assertGreater( abs(energies[energy_index_1] - energies[energy_index_2]), 1e-2) test.assertEqual(last_result, min(results, key=lambda result: result[1])) if __name__ == "__main__": for index, (cell, energy) in enumerate(results): print("{} of {}: {} with E={}".format(index + 1, len(results), cell, energy)) visualization.cell_mayavi(cell, [3] * cell.dimensions, [1] * cell.atom_types)
def test_incongruent_ensemble_count(self): ens = ensemble.EnsembleFilter(congruent=False) ppot = { (0, 0): potential.LennardJonesType(epsilon=1), (1, 1): potential.LennardJonesType(epsilon=0.5), (0, 1): potential.LennardJonesType(epsilon=0.25)} distance = 3.0 # Allow all of them through since only 64 total count = 100 # > 12+52 generator = ens.filter(['p1', 'p2'], (1,2), 3, ppot, distance, count, angles=(numpy.pi/2.0,), length_ratios=(1.0,), cores=_CORES, radii=(0.5,0.5), callback=None) self.assertEqual(len([b for a,b in enumerate(generator)]), 12+52) # Allow only best 10 through count = 10 generator = ens.filter(['p1', 'p2'], (1,2), 3, ppot, distance, count, angles=(numpy.pi/2.0,), length_ratios=(1.0,), cores=_CORES, radii=(0.5,0.5), callback=None) self.assertEqual(len([b for a,b in enumerate(generator)]), count)
def test_congruent_ensemble_count(self): ens = ensemble.EnsembleFilter(congruent=True) ppot = { (0, 0): potential.LennardJonesType(epsilon=1), (1, 1): potential.LennardJonesType(epsilon=0.5), (0, 1): potential.LennardJonesType(epsilon=0.25)} distance = 3.0 # Allow all of them through count = 2000 # > 1596 which there are for p1 with Ng = 4 generator = ens.filter(['p1'], (1,2), 4, ppot, distance, count, angles=(numpy.pi/2.0,), length_ratios=(1.0,), cores=_CORES, radii=(0.5,0.5), callback=None) self.assertEqual(len([b for a,b in enumerate(generator)]), 1596) # Allow some of them through count = 100 # > 1596 which there are for p1 with Ng = 4 generator = ens.filter(['p1'], (1,2), 4, ppot, distance, count, angles=(numpy.pi/2.0,), length_ratios=(1.0,), cores=_CORES, radii=(0.5,0.5), callback=None) self.assertEqual(len([b for a,b in enumerate(generator)]), count)
def test_sigma(self): # Check length scaling and shifting potential1 = potential.LennardJonesType() potential2 = potential.Transform(potential1, sigma=1.23, s=0.0456) r1 = numpy.linspace(0.9, 2, 100) r2 = (r1 + 0.0456) * 1.23 u1, f1 = potential1.evaluate_array(r1) u2, f2 = potential2.evaluate_array(r2) self.assertTrue(numpy.all(numpy.isclose(u1, u2))) self.assertTrue(numpy.all(numpy.isclose(f1, f2 * 1.23)))
def test_energyhistogramcallback(self): ens = ensemble.EnsembleFilter(congruent=False) ppot = { (0, 0): potential.LennardJonesType(epsilon=1), (1, 1): potential.LennardJonesType(epsilon=0.5), (0, 1): potential.LennardJonesType(epsilon=0.25)} distance = 3.0 # Sort all the energies if we allow all to go through count = 10 cback = ensemble.EnergyHistogramCallback(count=count) generator = ens.filter(['p1', 'p2'], (1,2), 3, ppot, distance, count, angles=(numpy.pi/2.0,), length_ratios=(1.0,), cores=_CORES, radii=(0.5,0.5), callback=cback) dummy = [b for a,b in enumerate(generator)] self.assertEqual(len(cback.below_threshold), count) self.assertEqual(len(cback.above_threshold), 64-count) self.assertTrue(all(cback.below_threshold[i] <= cback.below_threshold[i+1] for i in range(len(cback.below_threshold)-1)))
def test_evaluate_range(self): # Range evaluation simply works with 1-D numpy arrays potentials = [ potential.Transform(potential.LennardJonesType()), potential.Piecewise(potential.Potential(), potential.Piecewise( \ potential.JaglaType(), potential.Potential(), 1.05), 1)] r = numpy.linspace(0.5, 2, 100) for potential_object in potentials: u, f = potential_object.evaluate_array(r) for i in range(len(r)): ui, fi = potential_object.evaluate(r[i]) self.assertEqual(u[i], ui) self.assertEqual(f[i], fi)
def test_piecewise(self): # Check piecewise behavior (evaluating at cutoff calls far potential) potential1 = potential.JaglaType() potential2 = potential.LennardJonesType() piecewise = potential.Piecewise(potential1, potential2, 1.05) r1, r2 = numpy.linspace(1, 1.05, 100), numpy.linspace(1.05, 2, 100) ui1, fi1 = potential1.evaluate_array(r1) ui2, fi2 = potential2.evaluate_array(r2) up1, fp1 = piecewise.evaluate_array(r1) up2, fp2 = piecewise.evaluate_array(r2) self.assertTrue(numpy.all(numpy.isclose(ui1[:-1], up1[:-1]))) self.assertTrue(numpy.all(numpy.isclose(ui2, up2))) self.assertTrue(numpy.all(numpy.isclose(fi1[:-1], fp1[:-1]))) self.assertTrue(numpy.all(numpy.isclose(fi2, fp2)))
def test_congruent_ensemble_values_all(self): ens = ensemble.EnsembleFilter(congruent=True) ppot = { (0, 0): potential.LennardJonesType(epsilon=1), (1, 1): potential.LennardJonesType(epsilon=0.5), (0, 1): potential.LennardJonesType(epsilon=0.25)} distance = 3.0 # Sort all the energies if we allow all to go through count = 2000 energies = [None, None] def filter_callback(filter_energies): energies[0] = filter_energies[:count] energies[1] = filter_energies[count:] generator = ens.filter(['p1'], (1,2), 4, ppot, distance, count, angles=(numpy.pi/2.0,), length_ratios=(1.0,), cores=_CORES, radii=(0.5,0.5), callback=filter_callback) dummy = [b for a,b in enumerate(generator)] self.assertEqual(len(energies[0]), 1596) self.assertEqual(len(energies[1]), 0) self.assertTrue(all(energies[0][i] <= energies[0][i+1] for i in range(len(energies[0])-1)))
def test_incongruent_ensemble_values_fraction(self): ens = ensemble.EnsembleFilter(congruent=False) ppot = { (0, 0): potential.LennardJonesType(epsilon=1), (1, 1): potential.LennardJonesType(epsilon=0.5), (0, 1): potential.LennardJonesType(epsilon=0.25)} distance = 3.0 # Sort top fraction of energies count = 10 energies = [None, None] def filter_callback(filter_energies): energies[0] = filter_energies[:count] energies[1] = filter_energies[count:] generator = ens.filter(['p1', 'p2'], (1,2), 3, ppot, distance, count, angles=(numpy.pi/2.0,), length_ratios=(1.0,), cores=_CORES, radii=(0.5,0.5), callback=filter_callback) dummy = [b for a,b in enumerate(generator)] self.assertEqual(len(energies[0]), count) self.assertEqual(len(energies[1]), 64-count) self.assertTrue(all(energies[0][i] <= energies[0][i+1] for i in range(len(energies[0])-1)))
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)))
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])
class TaskManagerTests(unittest.TestCase): _default_potentials = { (0, 0): potential.LennardJonesType(lambda_=0.5), (0, 1): potential.LennardJonesType(lambda_=1.0), (1, 1): potential.LennardJonesType(lambda_=0.25) } # Note: specifying basinhopping niter=X yields X+1 callback invocations def test_default(self): # Make sure system runs with no crashes task_manager = automation.TaskManager([ (dict(stoichiometry=(1, 2), place_max=4, sample_count=4, log_level=2, sample_groups=[ WallpaperGroup(number=i + 1) for i in range(2) ]), dict(potentials=TaskManagerTests._default_potentials, distance=4, log_level=2, basin_kwargs=dict(niter=5), save_all=True, save_count=3)) ]) task_manager.work("data/testdb_default.db") # Make sure all processing did complete db = automation.ResultsDatabase("data/testdb_default.db") self.assertEqual(len(list(db.cells_in)), 4) self.assertEqual(len(list(db.cells_out)), 12) def test_preprocessor(self): # Make sure processor gets called on each input task_manager = automation.TaskManager( [(dict( stoichiometry=(1, 2), place_max=4, sample_count=4, log_level=2, sample_groups=[WallpaperGroup(number=i + 1) for i in range(2)]), dict(potentials=TaskManagerTests._default_potentials, distance=4, log_level=2, basin_kwargs=dict(niter=5), save_all=True, save_count=3))], preprocessors=[_custom_processor]) with open("data/testdb_check.in", mode="wb") as f: pass task_manager.work("data/testdb_preprocessor.db") with open("data/testdb_check.in", mode="rb") as f: self.assertEqual(len(f.read()), 4) def test_postprocessor(self): # Make sure processor gets called on each output task_manager = automation.TaskManager( [(dict( stoichiometry=(1, 2), place_max=4, sample_count=4, log_level=2, sample_groups=[WallpaperGroup(number=i + 1) for i in range(2)]), dict(potentials=TaskManagerTests._default_potentials, distance=4, log_level=2, basin_kwargs=dict(niter=5), save_all=True, save_count=3))], postprocessors=[_custom_processor]) with open("data/testdb_check.in", mode="wb") as f: pass task_manager.work("data/testdb_preprocessor.db") with open("data/testdb_check.in", mode="rb") as f: self.assertEqual(len(f.read()), 12) def test_multiple_jobs(self): # Make sure that system can handle multiple jobs task_manager = automation.TaskManager( [(dict( stoichiometry=(1, 2), place_max=4, sample_count=2, log_level=2, sample_groups=[WallpaperGroup(number=i + 1) for i in range(2)]), dict(potentials=TaskManagerTests._default_potentials, distance=4, log_level=2, basin_kwargs=dict(niter=5), save_all=True, save_count=3))] * 2) task_manager.work("data/testdb_multiple_jobs.db") # All processing should have still happened db = automation.ResultsDatabase("data/testdb_multiple_jobs.db") self.assertEqual(len(list(db.cells_in)), 4) self.assertEqual(len(list(db.cells_out)), 12) def test_filter(self): task_manager = automation.TaskManager( [(dict( stoichiometry=(1, 2), place_max=4, sample_count=20, log_level=2, sample_groups=[WallpaperGroup(number=i + 1) for i in range(2)]), dict(potentials=TaskManagerTests._default_potentials, distance=4, log_level=2, basin_kwargs=dict(niter=5), save_all=True, save_count=3))], preprocessors=[ automation.AutoFilteringProcessor(count=2), automation.ScalingProcessor((0.5, 0.5)) ]) task_manager.work("data/testdb_filter.db") # Make sure that filtering did happen db = automation.ResultsDatabase("data/testdb_filter.db") self.assertEqual(len(list(db.cells_in)), 4) self.assertEqual(len(list(db.cells_out)), 12)